Fork me on GitHub

Grupo de desenvolvedores de PHP do estado de São Paulo
Próximos encontros e eventos? Visite a página do PHPSP no Meetup

PHP WebDriver

Por em em Artigos,Software

Dos ultimos anos pra cá foi possível notar que o Facebook adora PHP, este artigo exalta mais uma prova disso: O PHP WebDriver.

O que é o WebDriver?

PHP WebDriver é uma API que permite automatizar interações com navegadores Web através de código PHP. Suas utilidades são, por exemplo, testes – aceitação, fluxo, integrações… – e, meu favorito, Crawlers.

Antes de explicar sobre o WebDriver, precisamos falar sobre Selenium e você também deverá saber que estamos lidando com o Java. Sim, este é o primeiro ponto a se notar: Não é uma implementação nativa com PHP, trata-se de uma integração.

Selenium é uma ferramenta de automação de navegador. Basicamente ele possui um Servidor de Controle Remoto que é responsável por abrir e fechar instâncias de navegadores e também servir de proxy para estas.

Para interagir com o servidor Selenium, utilizamos WebDrivers: drivers específicos capazes de enviar comandos aos navegadores que oferecem suporte. No momento em que escrevo este artigo, pode-se verificar nove drivers desenvolvidos.

E para interagir com com os drivers utilizamo-nos de uma API, e foi aí que o Facebook nos deu mais uma forcinha. – Estou ignorando completamente o fato de que eles estão entre os editores da RFC que descreve o WebDriver.

Facebook’s PHP WebDriver

Com o primeiro release em Outubro de 2013, o perfil Facebook no github conta com o repositório php-webdriver, também disponível no packagist para usuários de composer.

Trata-se de uma API similar às existentes em outras linguagens – Java, Python, Ruby, JavaScript, .NET – com o maior intuito de oferecer a mesma interface de programação.

Sua utilização é muito simples, porém exige um Selenium Server rodando, portanto dê uma olhada nos dois primeiros tópicos presentes no repositório php-webdriver.

O resultado, hoje, foi:

string(93) "Grupo de Desenvolvedores de PHP de São Paulo | Grupo de Desenvolvedores de PHP de São Paulo"

É importante também se certificar de que seu Selenium Server possui o driver que você procura.

Na prática

Existem outros artigos e até mesmo ferramentas que indicarão o webdriver como ferramenta de testes. Incluindo este texto.

No TDC 2015 recebemos, inclusive, uma excelente apresentação sobre uma ferramenta chamada Codeception, que também se baseia no Selenium. Com uma ferramenta assim, eu não correria atrás de escrever testes no PHPUnit usando o WebDriver diretamente.

O exemplo prático que lhes apresentarei, portanto, será o desenvolvimento de um crawler.

Nosso projeto de exemplo

O site do jogo Tibia possui um ranking de jogadores por servidor, para consulta via web-page. Se quisessemos disponibilizar, de alguma forma, isto à outras aplicações não existiria forma limpa. Optaremos, portanto, pela criação de um crawler que irá acessar estes rankings e obter os dados de maneira organizada.

O ranking pode ser acessado através deste link e não requer qualquer tipo de autenticação, o que torna nossa vida um pouco mais fácil.

Com o Selenium já de pé, iniciaremos nossa missão configurando o navegador:

Até aqui não há muita novidade, apenas acessamos a página utilizando o Firefox/Iceweasel. Acessando o link você poderá notar que requer um filtro inicial: devemos escolher qual servidor queremos visualizar através de uma select-box. Depois deve-se clicar no botão “Submit”.

Com toda astúcia do mundo descobrimos que o select-box pode ser encontrado com um seletor CSS: select[name=world] , assim como o botão Submit: input[name=Submit] .

Nossa vida vem ficando cada vez mais fácil:

Após enviar o click, a página vai ser atualizada (realizamos uma submissão de formulário) e, quando terminar, existirá em si agora uma tabela abaixo do filtro. No caso desta página, não existem muitas classes ou IDs CSS que facilitem nossa vida, optei então por buscar através de características das TRs: São zebradas que variam entre as cores #F1E0C6  e #D4C0A1 .

Obtemos as linhas de resultado assim:

$linhasResultado é um array que contém objetos do tipo  Facebook\WebDriver\Remote\RemoteWebElement . Como nem tudo é perfeito, nesta página existe outra linha que possui a cor  #F1E0C6 e, portanto, entraria na nossa lista de elementos. Para contornar isto verifiquei o número de elementos do tipo coluna dentro de cada linha, pois o Ranking se apresenta sempre com 4 colunas: Posição, Jogador, Nível e Pontuação. (Talvez exista um seletor CSS que verifique o número de filhos…)

A unica característica marcante estre estas colunas foi o tamanho em porcentagem:

É interessante notar que os nossos comandos rodam de forma totalmente síncrona, aguardando o carregamento e término de interações com o navegador a cada linha.

Com isso temos o seguinte produto final:

Após a execução, o código acima deverá gerar uma saída semelhante à esta (executado em 14/09/2015):

 

Conclusão

O php webdriver é mais um ótimo item para se guardar da caixa de ferramentas, tanto para testes quanto para obtenção de dados não disponíveis de forma comum. Sendo a segunda opção mais interessante, pois para testes existem outras ferramentas específicas para tanto.

Desenvolver crawlers utilizando o WebDriver é interessantíssimo porque, diferente de o que estamos acostumados, ele não apenas obtém os dados por alguma forma de cURL, mas trabalha a interação como um usuário de verdade, passando por cada validação de formulário, interação do navegador, atualização do DOM, execução de JavaScript e outros itens que só acontecem no navegador. Torna-se util a partir do momento que nosso crawler não busca apenas páginas estáticas. Além disso, o resultado das interações é visual e o Selenium permite tomar até mesmo obter capturas de tela do navegador em tempo de execução.

Tags: , , , , , , ,

Sobre Níckolas Silva

Desenvolvedor php há aproximadamente 4 anos, Níckolas é tecnólogo em Análise e Desenvolvimento de Sistemas, pós graduando em Engenharia de Software com foco em SOA e já esteve envolvido com desenvolvimento de sistemas de telecom e de gestão. Hoje dedica horas de seus dias ao estudo de tecnologias, práticas e técnicas sobre sistemas distribuídos, procurando integrar todas as áreas de atuação através destes estudos. Além disso está presente em todos eventos PHPSP+Pub, pois acredita que conversas, pessoas e cerveja são a chave para aprender e fortalecer conceitos.

Mais posts de .

  • Junior Filipin

    É, no exemplo acredito que seria MUITO melhor usar cURL com DOMDoc mesmo… fiquei me perguntando antes da conclusão o porquê de usar webdriver (não conhecia) ao invés dos métodos tradicionais, então vi que o mesmo executa JS. Dessa forma deve-se utilizar esse método somente presumindo que haverá execução importante de JS, pois esse negócio de webdriver com toda certeza usa MUITO mais recursos que um simples DOMDoc. E na verdade, mesmo com execução de JS, os dados obviamente serão obtidos por XHTTP, logo, seria melhor inspecionar as requisições pelo chrome antes, e usar o cURL mesmo nas URLs. Me corrija se estiver errado :)

  • Nawarian Níckolas

    De fato, Junior, usar cURL e DOMDoc resolveria boa parte do problema para este exemplo.
    A utilização do WebDriver é mais feliz em operações mais complexas e chatas, por assim dizer.

    Por exemplo: a criação de robôs para consultas em plataformas que exigem um navegador específico ou certificados digitais, ou mesmo uma extensão de navegador que só exista para o Chrome ou Firefox. São apenas exemplos…
    A magia do WebDriver aqui se dá por simular uma interação real com o usuário.

    Realmente, nem sempre vai ser a melhor das opções. Mas acredito que é um tiro certeiro nestes pontos que indiquei.

    Obrigado pela contribuição :)

  • Concordo, tenho um amigo que está utilizando-o para extrair dados de um relatório de precificação que só seria possível manualmente.

  • Bom post.
    Gostei da ideia de usar o Selenium para criar crawlers, uma mão na roda quando o site não tem uma API e usa Javascript.
    Para trabalhar com a interface acho até um pouco mais confiável e estável do que DOMDocument.

  • Daniel Vieira Junior

    Fala galera, sou novo aqui e comecei a mexer agora com webdriver em php e java, tirem uma dúvida minha por favor, se eu startar o selenium-server num servidor web…as pessoas que acessarem minha aplicação, o browser, firefox por exemplo, a Thread vai ser aberto na máquina que esta acessando a aplicação ou no servidor??

  • Perdão a demora, Daniel. Seria no lado servidor, no caso. Diria inclusive que no servidor onde está alocado o Selenium ^^

  • Valeu o/

  • William B. Pereira

    E ao pesquisar por Selenium com PHP deparo-me com a foto de um pequeno gafanhoto.. hsuah… boa pequeno gafanhoto!

  • Paulo Henrique Silva

    Ótimo artigo! Na próxima faz um artigo sobre esperas com selenium.