Web Scraping e Web Crawler — Introdução e Passos Iniciais

NetCoders
netcoders
Published in
6 min readAug 7, 2015

O QUE É?

Web Crawler, em português significa rastreador web, utilizado como um programa de computador que navega pela World Wide Web de uma forma metódica e automatizada.

Hoje é bastante comum ver a utilização destes sistemas autômatos em grandes empresas que necessitam buscar alguma informação em sites diversos.

SINÔNIMOS
Outro termos utilizados para Web Crawler são: Bots, Web Spider, Web Robot, Web Scutter entre outros.

PORQUE USAR?

No mundo tecnológico atual, tudo gira em torno de um única palavra, “Tecnologia”. Como melhorar? Como mudar? Como encontrar as informações que preciso?

Pensando nisso, pessoas do mundo todo começaram a trabalhar na captura de buscas de informações, sejam elas via Web Service ou via Automação Web (Web Crawler).

São inúmeras as possibilidades de automação de páginas, um bom exemplo de como e por que utilizar:

Você decidiu criar um aplicativo que exibe os posts de vários sites da web em um único local, então começam a surgir as perguntas que começam a inviabilizar o negócio:

  • Será que consigo um web service para carregar os posts?
  • Quanto vai custar este web service?
  • Disponho deste dinheiro?

Essas são apenas algumas perguntas que irão te direcionar para o método mais rápido e barato, o Web Crawler.
São situações como esta que se nos incentivam a fazer uma automação web, pois se trata de um trabalho rápido e de baixo custo.

PROBLEMAS:
O Site pode mudar constantemente e isso acaba saindo fora do controle do programador, pois terá que viver fazendo atualizações para que a automação contemple as novas mudanças do site.

O Site pode bloquear seu IP, devido à alta quantidade de acessos em um curto período de tempo e vários acessos simultâneos do mesmo IP.

Alguns sites fazem a identificação de acessos excessivos e por fim nega o acesso ao IP da sua aplicação.

Alguns Sites podem entrar com um processo contra você por acessos indevidos e não autorizados, então sempre tenha os termos de uso do Site em mãos e sempre que possível mantenha uma conversa constante com o proprietário do site para evitar problemas futuros.

Mãos à Obra:
Chega de lenga lenga e vamos “pôr a mão na massa”.

Abra o Visual Studio clique em um novo projeto (Estou utilizando o 2012 porém pode ser utilizada qualquer versão do visual studio).

NovoProjeto

Agora vamos baixar as dependências necessárias.
HtmlAgilityPack — Versão 1.4 ou superior.

AdicionandoReferencias

Importante! Faça um Build para ver se suas referências estão OK. Pois se tivermos problemas depois com elas será mais difícil de identificar onde está o problema.

Projeto ok? Inclua um componente DataGridView, pois nele que iremos mostrar os Posts capturados.
Altere seu nome para dgvPosts.

AdicionandoDataGrid

Crie 3 Classes:
Robo.cs ( Nela vamos colocar os métodos de que fazem ).
RoboWebClient.cs ( Nela vamos fazer um override de um método do WebClient para facilitar nossa utilização ).
NetCoders.cs ( Nesta classe está a lógica da busca e preenchimento dos campos ).

Na classe Robo.cs inclui os seguinte código:

[code language=”csharp”]
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.IO;
namespace Automacao
{
/// <summary>
/// Classe para utilização do Web Request.
/// </summary>
public class Robo
{
public RoboWebClient RoboWebClient { get; set; }

/// <summary>
/// Métodos para efetuar chamadas via GET.
/// </summary>
/// <param name=”url”>Url a ser pesquisada.</param>
/// <returns>HtmlDocumento — utilizado para facilitar o parse do Html.</returns>
public HtmlDocument HttpGet( string url)
{
lock ( this )
{
var htmlDocument = new HtmlDocument();
htmlDocument.LoadHtml( RoboWebClient.DownloadString( url ));

return htmlDocument;
}
}

/// <summary>
/// Método para efetuar chamadas via POST
/// </summary>
/// <param name=”url”>Url a ser pesquisada.</param>
/// <param name=”parametros”>Parâmetros da página.</param>
/// <returns>HtmlDocumento — utilizado para facilitar o parse do Html.</returns>
public HtmlDocument HttpPost( string url, NameValueCollection parametros)
{

var htmlDocument = new HtmlDocument();
byte[] pagina = RoboWebClient.UploadValues( url, parametros);
htmlDocument.LoadHtml( Encoding.Default.GetString( pagina, 0, pagina.Count() ) );

return htmlDocument;
}
}

}

[/code]

Código da classe RoboWebClient.cs:

[code language=”csharp”]
using System;
using System.IO;
using System.Net;
using System.Text;
namespace Automacao
{
public class RoboWebClient : WebClient
{
//Criei estas propriedades apenas para controle.
//Caso preciso expor essas propriedades para alteração basta tirar o readonly e alterar para public.
//Lembre-se os sites podem variar e muito, então expor uma variável pode deixar seu código mais flexivel.
public CookieContainer _cookie = new CookieContainer();
public bool _allowAutoRedirect;

/// <summary>
/// fiz um override do método para contemplar as variveis expostas.
/// neste caso esta privadas, mas para o caso de expor, deve seguir a forma abaixo.
/// </summary>
/// <param name=”address”>Endereço de busca.</param>
/// <returns>Retorno da requisição a ser tratada.</returns>
protected override WebRequest GetWebRequest( Uri address )
{

WebRequest request = base.GetWebRequest( address );
if ( request is HttpWebRequest )
{
(request as HttpWebRequest ).ServicePoint.Expect100Continue = false;
(request as HttpWebRequest ).CookieContainer = _cookie;
(request as HttpWebRequest).KeepAlive = false;
(request as HttpWebRequest).AllowAutoRedirect = _allowAutoRedirect;
}

return request;
}
}
}

[/code]

Classe NetCoders.cs

[code language=”csharp”]
using Automacao;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebCrawler
{
public class NetCoders : Robo
{
/// <summary>
/// Construtor para instânciar o Client
/// </summary>
public NetCoders()
{
RoboWebClient = new RoboWebClient();
}

/// <summary>
/// Método onde é feito o crawler para carregar os posts.
/// </summary>
/// <returns>Lista de artigos ordenada por data.</returns>
public List<artigo> CarregaPosts()
{
NameValueCollection parametros = new NameValueCollection();
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
//Carrega a página inicial do Blog.
//Estou atribuindo o resultado ao HtmlAgilityPack para fazer o parse do HTML.
this.RoboWebClient._allowAutoRedirect = false;
var ret = this.HttpGet(@”http://netcoders.com.br/");

//Capturando apenas as tags que estão definidas como article e ordenando pelo ID de cada Tag.
var artigosOrdenados = ret.DocumentNode.Descendants().Where(n => n.Name == “article”).OrderBy(d => d.Id).ToList();
List<artigo> artigos = new List<artigo>();

//Percorrendo os artigos que ja foram selecionados.
foreach (var item in artigosOrdenados)
{
artigo art = new artigo();

//Carregando o Html de cada artigo.
doc.LoadHtml(item.InnerHtml);

//Estou utilizando o HtmlAgilityPack.HtmlEntity.DeEntitize para fazer o HtmlDecode dos textos capturados de cada artigo.
// Utilizo também o UTF8 para limpar o restante dos Encodes que estiverem na página.
art.Titulo = HtmlAgilityPack.HtmlEntity.DeEntitize(ConvertUTF(doc.DocumentNode.DescendantsAndSelf().FirstOrDefault(d => d.Attributes[“class”] != null && d.Attributes[“class”].Value == “post-title entry-title”).InnerText));
art.Data = Convert.ToDateTime(HtmlAgilityPack.HtmlEntity.DeEntitize(doc.DocumentNode.DescendantsAndSelf().FirstOrDefault(d => d.Name == “span” && d.Attributes[“class”].Value == “post-time”).InnerText));
art.Descricao = HtmlAgilityPack.HtmlEntity.DeEntitize(ConvertUTF(doc.DocumentNode.DescendantsAndSelf().FirstOrDefault(d => d.Attributes[“class”] != null && d.Attributes[“class”].Value == “entry-content”).InnerText));
art.Autor = HtmlAgilityPack.HtmlEntity.DeEntitize(ConvertUTF(doc.DocumentNode.DescendantsAndSelf().FirstOrDefault(d => d.Attributes[“class”] != null && d.Attributes[“class”].Value == “post-author”).InnerText));
artigos.Add(art);
}

return artigos.OrderBy(d=> d.Data).ToList();
}

private string ConvertUTF(string texto)
{
// Convertendo o texto para o Enconding default e Array de bytes.
byte[] data = Encoding.Default.GetBytes(texto);

//Convertendo o texto limpo para UTF8.
string ret = Encoding.UTF8.GetString(data);

return ret;
}

}

/// <summary>
/// Classe espelho do artigo.
/// </summary>
public class artigo
{
public string Titulo { get; set; }
public DateTime Data { get; set; }
public string Descricao { get; set; }
public string Autor { get; set; }
}
}

[/code]

Faça um build para ver se está tudo ok.

Estando ok, aperte F5 e corra pro abraço.

lembre-se que a criatividade que mandar realmente no WebCrawler, recomendo explorar ao extremo a lógica, pois, a lógica de pesquisas em arvores que manda na qualidade do WebCrawler devido ao grande número de pesquisas nas tags HTML.

Obs.:Logo disponibilizarei alguns métodos mais completos, como Post, UserAgent 4.5 e 5.0, coleta de cookies.

--

--