SlideShare uma empresa Scribd logo
1 de 42
Baixar para ler offline
Gustavo Almeida
WEB Crawling && Scraping
Coleta de dados na WEB com PHP
1
$whoami
2
Definições
Crawling (rastreador) = spider, rastreador, rastreador focado, robô.
Scraping (raspagem) = RI (Recuperação da Informação), EI (Extração da Informação).
Interpretação = data mining (mineração de dados), SQL, IA (Inteligência Artificial).
Devido a longos tempos de processamento usamos PHP-CLI - linha de comando (tela escura).
Coleta de dados - pelo menos 2 etapas :.
● busca / listagem
● detalhe / perfil
3
4
www.internetlivestats.com
Curiosidades - Google (1998)
urls = [‘siteA.com’] #seed / sementes
foreach(urls as url){
requisicaoGET(siteA.com)
extrai(“<a href=’http://siteB.com’>link B</a>”)
requisicaoGET(‘siteB.com’)
extrai(“<a href=’http://siteC.com’>link C</a>”)
requisicaoGET(‘siteC.com’)
… e assim vai ...
Basicamente temos um esquema de GRAFOS.
Bread First Search - Busca em Largura
Deep First Search - Busca em Profundidade
5
- O primeiro crawling foi feito em 1993
- Google não é pioneiro - 1994 https://en.wikipedia.org/wiki/World-Wide_Web_Worm
Coleta de dados - O problema
1. Recuperar a informação (HTML) que está em um servidor web.
2. Fazer isso para uma grande quantidade.
3. Fazer isso automaticamente (robô).
4. Reunir informação (Banco de Dados)
5. Responder as perguntas (T-SQL) de quem te contratou.
6
Coleta de dados - O problema
7
WEB
BD
Qual a sua pergunta ?
Caso de uso bem simples para a palestra :.
Quero vender um carro! Qual preço devo anunciar ?
Vamos supor que não existisse a tabela FIPE.
Qual a média de preço de um golf ano 2010 na internet ?
8
Principais pontos
● robots.txt
● header User-Agent
● RapidFire
● Rotating IP
● Horários de pico
● Duplicação de páginas
● RIAs e sites com autenticação
● Captchas
● Timeout
● BD Mysql
9
arquivo robots.txt
10
Usa o formato do Protocolo de
Exclusão de Robôs padrão,
serve para dar ordens
específicas para os robôs de
busca.
robots.txt
11
LinkedIn perdeu na justiça ao impedir uma empresa de fazer scraping
SSL && header User-Agent
Podemos recuperar a pagina HTML do servidor com varias funcoes PHP
● file
● fopen
● file_get_contents
Conforme o servidor alvo começa a ficar exigente temos que trabalhar com outras funções
● cURL
● stream_context_create
12
SSL && header User-Agent
13
RapidFire
Evitar bombardear requisições no site alvo. Podemos usar um intervalo randômico.
sleep(mt_rand(5,10));
Esse código antes de qualquer requisição GET ou POST simula aleatoriedade.
14
IP
Podemos ser bloqueados pelo IP, neste caso podemos usar um proxy via Curl
$proxy = "1.1.1.1:33333";
$useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1";
$url = "https://api.ipify.org/";
$ch = curl_init();
curl_setopt($ch, CURLOPT_HTTP_VERSION,'CURL_HTTP_VERSION_1_1' );
curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);
curl_setopt($ch, CURLOPT_PROXY, $proxy);
curl_setopt($ch, CURLOPT_PROXYUSERPWD,'USER:PASS');
curl_setopt($ch, CURLOPT_USERAGENT,$useragent);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0);
$result=curl_exec ($ch);
curl_close ($ch);
echo $result;
15
Auth && RIA - Rich Internet App (ajax)
Quando as informações são processadas no browser via AJAX - Problema para PHP
16
Auth && RIA - Rich Internet App (ajax)
Solução ? Selenium - Webdriver
O cliente do webdriver para PHP:
composer require facebook/webdriver
java -jar selenium-server-standalone-#versao.jar
$host = 'http://localhost:4444/wd/hub';
$driver=RemoteWebDriver::create($host,DesiredCapabilities::firefox());
$driver->get(‘www.linkedin.com/login’);
$login=$driver->findElement(WebDriverBy::name('session_key'));
$login->sendKeys('email@gmail.com');
$senha=$driver->findElement(WebDriverBy::name('session_pass'));
$senha->sendKeys('minhasenha');
$submit=$driver->findElement(WebDriverBy::id('btn-primary'));
$submit->click();
for($i=1; $i<=20; $i++){
$driver->get(‘www.linkedin.com/busca/params/pag=’.$i);
...
17
Captchas - usei cURL + Selenium
Extrair esta imagem Como ? GD?
1) cURL nao faz printScreen. Selenium sim.
2) Recortei o captcha - Salvei a img via GD.
3) Transformei todos os pixels não pretos em branco.
4) Com cURL envio esta imagem via POST para um programa
específico que acerta +-30%.
18
Cronjob - Agendador de tarefas
19
crontab meuagendador.txt
crontab -l
Timeout - CLI (Command Line Interface)
$_ = $_SERVER['_']; (Retorna o binário /usr/bin/php)
$restartMyself = function () {
global $_, $argv;
pcntl_exec($_, $argv);
};
register_shutdown_function($restartMyself);
set_error_handler($restartMyself , E_ALL);
Este codigo faz o script PHP rodar o
tempo todo, mesmo que finalize o loop
do BD ou se der erros.
20
utf-8
21
BD (fazer a limpeza antes)
Eliminar espaços (“ “), quebras linha (n) e tabs (t) antes de armazenar no BD
preg_replace('/(?:ss+|n|t)/', ' ', $html);
Usar constraints UNIQUE para evitar repetidos.
UNIQUE KEY `uq_link_paginacao` (`link`,`paginacao`)
Tipos de dados no MYSQL exemplos de campos :
- flag/booleano : tinyint(1) default ‘0’
- paginas html : longtext()
Fique atento com o tamanho do BD : (Linux 2.4+ ext3 file system) +- 4TB
22
se não couber no seu computador - você está lidando com um BIGDATA
Crawling
23
‘Hello World’ da Coleta de dados
24
25
26
27
Paginação é crucial
28
Paginação - pseudocodigo
29
$url = ‘www.icarros.com.br/listagem...blabla…&pag=1’;
$html = crawling($url);
#Núm. de paginas no 1º Crawling (Regex || DOM)
$paginas = getTotalPaginas($html);
for($i=2; $i<=$paginas; $i++){
$url = ‘www.icarros.com.br/listagem...blabla…&pag=’. $i;
crawling($url);
}
Scraping
30
31
DOMDocument
32
Navega na árvore DOM até
chegar no nó desejado.
$dom = new DOMDocument();
$dom->loadHTML($html);
foreach($dom->getElementsByTagName(‘a’) as $link){
echo $link->getAttribute(‘href’);
}
Regex em PHP
33
preg_match(‘/ regex /’,$html,$matches);
34
regex101.com
35
codebeautify.org
listagem
PSEUDOCODIGO
$urls =
[
‘icarros’=>’www.icarros.com.br/busca.blabla…&tag=golf’,
‘webm’=>‘www.webmotors.com.br/busca…tag2=golf’
];
foreach($urls as $key=>$url){
$html = crawling($url, $key);
$paginas = getInfoNumPaginas($html) ?? 0;
for($i=2; $i<=paginas;$i++){
crawling($site.’&pag=’.$i)
}
}
function crawling(string $url): string{
#varias opcoes
$html = file_get_contents($url)
$pag=explode(‘&’,$url)[‘pag’];
parseAndSave2BD($html,$url,$pag);
return $html
}
function parseAndSave2BD(string $html, $url, $pag=1): bool{
#aqui usamos Regex para extrair total e salvar tabela listagem
$q = “insert listagem set
url=’$url’,total=$total,pag=$pag
on duplicate key update
}
function getInfoNumPaginas($html): int{
return preg_match(‘/<li>(.+?)</li>/’,$html,$matches) ?? 0;
}
36
BD
37
a página de detalhes
contém informações
complementares.
detalhes
PSEUDOCODIGO
$ids = $cn->query(“select id from detalhes where parsed=0”);
foreach($ids as $id){
$html = crawling($url . $id)
$arrayInfo = getInfoViaRegex($html)
$arrayInfo = getInfoViaDOM($html)
saveData2BD($arrayInfo)
}
function getInfoViaRegex($html){
$preco = preg_match(‘/<td><a>(.+)</a></td>/’,$html);
$ano = preg_match(‘/<td><a>(.+)</a></td>/’,$html);
return [‘preco’=>$preco,’ano’=>$ano];
}
function getInfoViaDOM($html){
$dom = new DOMDocument();
$dom->loadHTML($html);
foreach($dom->getElementsByTagName(‘a’) as $link){
if($link->getAttribute(‘class’)==’preco’){
$preco = $link->item(0)->nodeValue;
}
}
...
return [‘preco’=>$preco,’ano’=>$ano];
}
function saveData2BD($arrayInfo){
global $cn; extract($arrayInfo);
$q=”update detalhes set parsed=1,campo2=$campo2”;
return $cn->exec($q);
} 38
BD - análise dos dados
listagem
id
url UNIQUE
pagina
total
detalhes
id
golf_id UNIQUE
parsed
listagem_id FK
preco
id url pg total
1 icarros.com/c=golf&...&pag=1 1 160
2 icarros.com/c=golf&...&pag=2 2 160
3 webmot.com/c=golf&...&pag=1 1 860
id golf_id FK preco
1 GFYR544 1 30000
2 KPYR774 1 29500
3 FFFF765445FFVYRE65HGF 3 33000
39
BD - análise e auditoria dos dados
40
select distinct sum(total) from listagem group by total;
select avg(preco) as media from detalhes;
41
github: lga37
slideshare: lga33
br.linkedin.com/in/lga37 42

Mais conteúdo relacionado

Semelhante a Coleta de dados na WEB com PHP

Web Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaWeb Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaSidney Roberto
 
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...tdc-globalcode
 
isk-daemon: busca visual de imagens para todos
isk-daemon: busca visual de imagens para todosisk-daemon: busca visual de imagens para todos
isk-daemon: busca visual de imagens para todosRicardo Cabral
 
Aplicações com Tecnologias Web
Aplicações com Tecnologias WebAplicações com Tecnologias Web
Aplicações com Tecnologias WebRildo Pragana
 
Arquitetando Soluções de Dados com PostgreSQL
Arquitetando Soluções de Dados com PostgreSQLArquitetando Soluções de Dados com PostgreSQL
Arquitetando Soluções de Dados com PostgreSQLRaul Oliveira
 
Oficina postgresql avançado_consegi2010
Oficina postgresql avançado_consegi2010Oficina postgresql avançado_consegi2010
Oficina postgresql avançado_consegi2010Fabrízio Mello
 
Busca Visual
Busca VisualBusca Visual
Busca Visualgsroma
 
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...Mauro Risonho de Paula Assumpcao
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkPablo Dall'Oglio
 
XSS Desvendado
XSS DesvendadoXSS Desvendado
XSS Desvendadoricardophp
 
DevDay - O elo perdido: sincronizando webapps
DevDay - O elo perdido: sincronizando webappsDevDay - O elo perdido: sincronizando webapps
DevDay - O elo perdido: sincronizando webappsSuissa
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmGuilherme Blanco
 
A Biblioteca cURL
A Biblioteca cURLA Biblioteca cURL
A Biblioteca cURLricardophp
 

Semelhante a Coleta de dados na WEB com PHP (20)

Pdo do PHP Palestra
Pdo do PHP PalestraPdo do PHP Palestra
Pdo do PHP Palestra
 
Doctrine for Dummies
Doctrine for DummiesDoctrine for Dummies
Doctrine for Dummies
 
Web Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciênciaWeb Scraping: aplicações nos negócios e na ciência
Web Scraping: aplicações nos negócios e na ciência
 
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...
TDC2016POA | Trilha Banco de Dados - Firebase e Realm, o NoSQL ganha força no...
 
MongoDB + PHP
MongoDB + PHPMongoDB + PHP
MongoDB + PHP
 
isk-daemon: busca visual de imagens para todos
isk-daemon: busca visual de imagens para todosisk-daemon: busca visual de imagens para todos
isk-daemon: busca visual de imagens para todos
 
Aplicações com Tecnologias Web
Aplicações com Tecnologias WebAplicações com Tecnologias Web
Aplicações com Tecnologias Web
 
Arquitetando Soluções de Dados com PostgreSQL
Arquitetando Soluções de Dados com PostgreSQLArquitetando Soluções de Dados com PostgreSQL
Arquitetando Soluções de Dados com PostgreSQL
 
Oficina postgresql avançado_consegi2010
Oficina postgresql avançado_consegi2010Oficina postgresql avançado_consegi2010
Oficina postgresql avançado_consegi2010
 
Mashups: Criando Valor na Web 2.0
Mashups: Criando Valor na Web 2.0Mashups: Criando Valor na Web 2.0
Mashups: Criando Valor na Web 2.0
 
Busca Visual
Busca VisualBusca Visual
Busca Visual
 
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...
OWASP AppSec 2010 BRAZIL Information Extraction Art of Testing Network Periph...
 
Doctrine for dummies
Doctrine for dummiesDoctrine for dummies
Doctrine for dummies
 
Programando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um FrameworkProgramando para programadores: Desafios na evolução de um Framework
Programando para programadores: Desafios na evolução de um Framework
 
XSS Desvendado
XSS DesvendadoXSS Desvendado
XSS Desvendado
 
Palestra MongoDB
Palestra MongoDBPalestra MongoDB
Palestra MongoDB
 
DevDay - O elo perdido: sincronizando webapps
DevDay - O elo perdido: sincronizando webappsDevDay - O elo perdido: sincronizando webapps
DevDay - O elo perdido: sincronizando webapps
 
PHP e Redis
PHP e RedisPHP e Redis
PHP e Redis
 
Desenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine OrmDesenvolvimento Agil Com Doctrine Orm
Desenvolvimento Agil Com Doctrine Orm
 
A Biblioteca cURL
A Biblioteca cURLA Biblioteca cURL
A Biblioteca cURL
 

Mais de Luis Gustavo Almeida

Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesLuis Gustavo Almeida
 
Palestra de segurança em PHP - Hacking
Palestra de segurança em PHP - HackingPalestra de segurança em PHP - Hacking
Palestra de segurança em PHP - HackingLuis Gustavo Almeida
 
ReactPHP && programacao assincrona em PHP
ReactPHP && programacao assincrona em PHPReactPHP && programacao assincrona em PHP
ReactPHP && programacao assincrona em PHPLuis Gustavo Almeida
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Luis Gustavo Almeida
 

Mais de Luis Gustavo Almeida (9)

Curso de HTML5 CSS3 e JS
Curso de HTML5 CSS3 e JSCurso de HTML5 CSS3 e JS
Curso de HTML5 CSS3 e JS
 
Php curl - Coleta de dados na web
Php curl - Coleta de dados na webPhp curl - Coleta de dados na web
Php curl - Coleta de dados na web
 
Geolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e RoutesGeolocalização em PHP - Google Places, Maps e Routes
Geolocalização em PHP - Google Places, Maps e Routes
 
Criando uma blockchain com PHP
Criando uma blockchain com PHPCriando uma blockchain com PHP
Criando uma blockchain com PHP
 
Php criptomoedas e blockchain
Php criptomoedas e blockchainPhp criptomoedas e blockchain
Php criptomoedas e blockchain
 
Palestra de segurança em PHP - Hacking
Palestra de segurança em PHP - HackingPalestra de segurança em PHP - Hacking
Palestra de segurança em PHP - Hacking
 
ReactPHP && programacao assincrona em PHP
ReactPHP && programacao assincrona em PHPReactPHP && programacao assincrona em PHP
ReactPHP && programacao assincrona em PHP
 
Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017 Mini Curso PHP Twig - PHP Conference 2017
Mini Curso PHP Twig - PHP Conference 2017
 
Migrando para PHP7 - Novidades
Migrando para PHP7 - NovidadesMigrando para PHP7 - Novidades
Migrando para PHP7 - Novidades
 

Coleta de dados na WEB com PHP

  • 1. Gustavo Almeida WEB Crawling && Scraping Coleta de dados na WEB com PHP 1
  • 3. Definições Crawling (rastreador) = spider, rastreador, rastreador focado, robô. Scraping (raspagem) = RI (Recuperação da Informação), EI (Extração da Informação). Interpretação = data mining (mineração de dados), SQL, IA (Inteligência Artificial). Devido a longos tempos de processamento usamos PHP-CLI - linha de comando (tela escura). Coleta de dados - pelo menos 2 etapas :. ● busca / listagem ● detalhe / perfil 3
  • 5. Curiosidades - Google (1998) urls = [‘siteA.com’] #seed / sementes foreach(urls as url){ requisicaoGET(siteA.com) extrai(“<a href=’http://siteB.com’>link B</a>”) requisicaoGET(‘siteB.com’) extrai(“<a href=’http://siteC.com’>link C</a>”) requisicaoGET(‘siteC.com’) … e assim vai ... Basicamente temos um esquema de GRAFOS. Bread First Search - Busca em Largura Deep First Search - Busca em Profundidade 5 - O primeiro crawling foi feito em 1993 - Google não é pioneiro - 1994 https://en.wikipedia.org/wiki/World-Wide_Web_Worm
  • 6. Coleta de dados - O problema 1. Recuperar a informação (HTML) que está em um servidor web. 2. Fazer isso para uma grande quantidade. 3. Fazer isso automaticamente (robô). 4. Reunir informação (Banco de Dados) 5. Responder as perguntas (T-SQL) de quem te contratou. 6
  • 7. Coleta de dados - O problema 7 WEB BD
  • 8. Qual a sua pergunta ? Caso de uso bem simples para a palestra :. Quero vender um carro! Qual preço devo anunciar ? Vamos supor que não existisse a tabela FIPE. Qual a média de preço de um golf ano 2010 na internet ? 8
  • 9. Principais pontos ● robots.txt ● header User-Agent ● RapidFire ● Rotating IP ● Horários de pico ● Duplicação de páginas ● RIAs e sites com autenticação ● Captchas ● Timeout ● BD Mysql 9
  • 10. arquivo robots.txt 10 Usa o formato do Protocolo de Exclusão de Robôs padrão, serve para dar ordens específicas para os robôs de busca.
  • 11. robots.txt 11 LinkedIn perdeu na justiça ao impedir uma empresa de fazer scraping
  • 12. SSL && header User-Agent Podemos recuperar a pagina HTML do servidor com varias funcoes PHP ● file ● fopen ● file_get_contents Conforme o servidor alvo começa a ficar exigente temos que trabalhar com outras funções ● cURL ● stream_context_create 12
  • 13. SSL && header User-Agent 13
  • 14. RapidFire Evitar bombardear requisições no site alvo. Podemos usar um intervalo randômico. sleep(mt_rand(5,10)); Esse código antes de qualquer requisição GET ou POST simula aleatoriedade. 14
  • 15. IP Podemos ser bloqueados pelo IP, neste caso podemos usar um proxy via Curl $proxy = "1.1.1.1:33333"; $useragent="Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.1) Gecko/20061204 Firefox/2.0.0.1"; $url = "https://api.ipify.org/"; $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTP_VERSION,'CURL_HTTP_VERSION_1_1' ); curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1); curl_setopt($ch, CURLOPT_PROXY, $proxy); curl_setopt($ch, CURLOPT_PROXYUSERPWD,'USER:PASS'); curl_setopt($ch, CURLOPT_USERAGENT,$useragent); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); curl_setopt($ch, CURLOPT_FOLLOWLOCATION,1); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER,0); $result=curl_exec ($ch); curl_close ($ch); echo $result; 15
  • 16. Auth && RIA - Rich Internet App (ajax) Quando as informações são processadas no browser via AJAX - Problema para PHP 16
  • 17. Auth && RIA - Rich Internet App (ajax) Solução ? Selenium - Webdriver O cliente do webdriver para PHP: composer require facebook/webdriver java -jar selenium-server-standalone-#versao.jar $host = 'http://localhost:4444/wd/hub'; $driver=RemoteWebDriver::create($host,DesiredCapabilities::firefox()); $driver->get(‘www.linkedin.com/login’); $login=$driver->findElement(WebDriverBy::name('session_key')); $login->sendKeys('email@gmail.com'); $senha=$driver->findElement(WebDriverBy::name('session_pass')); $senha->sendKeys('minhasenha'); $submit=$driver->findElement(WebDriverBy::id('btn-primary')); $submit->click(); for($i=1; $i<=20; $i++){ $driver->get(‘www.linkedin.com/busca/params/pag=’.$i); ... 17
  • 18. Captchas - usei cURL + Selenium Extrair esta imagem Como ? GD? 1) cURL nao faz printScreen. Selenium sim. 2) Recortei o captcha - Salvei a img via GD. 3) Transformei todos os pixels não pretos em branco. 4) Com cURL envio esta imagem via POST para um programa específico que acerta +-30%. 18
  • 19. Cronjob - Agendador de tarefas 19 crontab meuagendador.txt crontab -l
  • 20. Timeout - CLI (Command Line Interface) $_ = $_SERVER['_']; (Retorna o binário /usr/bin/php) $restartMyself = function () { global $_, $argv; pcntl_exec($_, $argv); }; register_shutdown_function($restartMyself); set_error_handler($restartMyself , E_ALL); Este codigo faz o script PHP rodar o tempo todo, mesmo que finalize o loop do BD ou se der erros. 20
  • 22. BD (fazer a limpeza antes) Eliminar espaços (“ “), quebras linha (n) e tabs (t) antes de armazenar no BD preg_replace('/(?:ss+|n|t)/', ' ', $html); Usar constraints UNIQUE para evitar repetidos. UNIQUE KEY `uq_link_paginacao` (`link`,`paginacao`) Tipos de dados no MYSQL exemplos de campos : - flag/booleano : tinyint(1) default ‘0’ - paginas html : longtext() Fique atento com o tamanho do BD : (Linux 2.4+ ext3 file system) +- 4TB 22 se não couber no seu computador - você está lidando com um BIGDATA
  • 24. ‘Hello World’ da Coleta de dados 24
  • 25. 25
  • 26. 26
  • 27. 27
  • 29. Paginação - pseudocodigo 29 $url = ‘www.icarros.com.br/listagem...blabla…&pag=1’; $html = crawling($url); #Núm. de paginas no 1º Crawling (Regex || DOM) $paginas = getTotalPaginas($html); for($i=2; $i<=$paginas; $i++){ $url = ‘www.icarros.com.br/listagem...blabla…&pag=’. $i; crawling($url); }
  • 31. 31
  • 32. DOMDocument 32 Navega na árvore DOM até chegar no nó desejado. $dom = new DOMDocument(); $dom->loadHTML($html); foreach($dom->getElementsByTagName(‘a’) as $link){ echo $link->getAttribute(‘href’); }
  • 33. Regex em PHP 33 preg_match(‘/ regex /’,$html,$matches);
  • 36. listagem PSEUDOCODIGO $urls = [ ‘icarros’=>’www.icarros.com.br/busca.blabla…&tag=golf’, ‘webm’=>‘www.webmotors.com.br/busca…tag2=golf’ ]; foreach($urls as $key=>$url){ $html = crawling($url, $key); $paginas = getInfoNumPaginas($html) ?? 0; for($i=2; $i<=paginas;$i++){ crawling($site.’&pag=’.$i) } } function crawling(string $url): string{ #varias opcoes $html = file_get_contents($url) $pag=explode(‘&’,$url)[‘pag’]; parseAndSave2BD($html,$url,$pag); return $html } function parseAndSave2BD(string $html, $url, $pag=1): bool{ #aqui usamos Regex para extrair total e salvar tabela listagem $q = “insert listagem set url=’$url’,total=$total,pag=$pag on duplicate key update } function getInfoNumPaginas($html): int{ return preg_match(‘/<li>(.+?)</li>/’,$html,$matches) ?? 0; } 36
  • 37. BD 37 a página de detalhes contém informações complementares.
  • 38. detalhes PSEUDOCODIGO $ids = $cn->query(“select id from detalhes where parsed=0”); foreach($ids as $id){ $html = crawling($url . $id) $arrayInfo = getInfoViaRegex($html) $arrayInfo = getInfoViaDOM($html) saveData2BD($arrayInfo) } function getInfoViaRegex($html){ $preco = preg_match(‘/<td><a>(.+)</a></td>/’,$html); $ano = preg_match(‘/<td><a>(.+)</a></td>/’,$html); return [‘preco’=>$preco,’ano’=>$ano]; } function getInfoViaDOM($html){ $dom = new DOMDocument(); $dom->loadHTML($html); foreach($dom->getElementsByTagName(‘a’) as $link){ if($link->getAttribute(‘class’)==’preco’){ $preco = $link->item(0)->nodeValue; } } ... return [‘preco’=>$preco,’ano’=>$ano]; } function saveData2BD($arrayInfo){ global $cn; extract($arrayInfo); $q=”update detalhes set parsed=1,campo2=$campo2”; return $cn->exec($q); } 38
  • 39. BD - análise dos dados listagem id url UNIQUE pagina total detalhes id golf_id UNIQUE parsed listagem_id FK preco id url pg total 1 icarros.com/c=golf&...&pag=1 1 160 2 icarros.com/c=golf&...&pag=2 2 160 3 webmot.com/c=golf&...&pag=1 1 860 id golf_id FK preco 1 GFYR544 1 30000 2 KPYR774 1 29500 3 FFFF765445FFVYRE65HGF 3 33000 39
  • 40. BD - análise e auditoria dos dados 40 select distinct sum(total) from listagem group by total; select avg(preco) as media from detalhes;
  • 41. 41