Html Agility Pack, Web Scraping y spoofing en C#
web-scraping html-agility-pack (2)
Use un navegador y un violín comunes (si las herramientas de desarrollador no están a la altura) y eche un vistazo a los encabezados de solicitud y respuesta.
Acumule sus solicitudes y solicite encabezados para que coincidan con lo que envía el navegador (puede usar un par de navegadores diferentes para evaluar si esto hace la diferencia).
En lo que respecta a "ser bloqueado después de una cierta cantidad de llamadas", acelere sus llamadas. Solo haz una llamada cada x segundos. Compórtate bien con el sitio y se comportará bien contigo.
Es probable que simplemente mire la cantidad de llamadas de su dirección IP por segundo y, si pasa un umbral, la dirección IP se bloquea.
¿Hay alguna forma de falsificar una solicitud web del código C # para que no parezca que un bot o spam llegue al sitio? Estoy tratando de raspar mi sitio web, pero sigo bloqueado después de una cierta cantidad de llamadas. Quiero actuar como un navegador real. Estoy usando este código, desde HTML Agility Pack.
var web = new HtmlWeb();
web.UserAgent =
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11";
Hago demasiado raspado web, pero estas son las opciones: Tengo una lista predeterminada de encabezados que agrego, ya que se esperan todos estos desde un navegador:
wc.Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.97 Safari/537.11";
wc.Headers[HttpRequestHeader.ContentType] = "application/x-www-form-urlencoded";
wc.Headers[HttpRequestHeader.Accept] = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
wc.Headers[HttpRequestHeader.AcceptEncoding] = "gzip,deflate,sdch";
wc.Headers[HttpRequestHeader.AcceptLanguage] = "en-GB,en-US;q=0.8,en;q=0.6";
wc.Headers[HttpRequestHeader.AcceptCharset] = "ISO-8859-1,utf-8;q=0.7,*;q=0.3";
(WC es mi WebClient).
Como ayuda adicional, esta es mi clase de cliente web que mantiene almacenadas las cookies, que también es una gran ayuda:
public class CookieWebClient : WebClient
{
public CookieContainer m_container = new CookieContainer();
public WebProxy proxy = null;
protected override WebRequest GetWebRequest(Uri address)
{
try
{
ServicePointManager.DefaultConnectionLimit = 1000000;
WebRequest request = base.GetWebRequest(address);
request.Proxy = proxy;
HttpWebRequest webRequest = request as HttpWebRequest;
webRequest.Pipelined = true;
webRequest.KeepAlive = true;
if (webRequest != null)
{
webRequest.CookieContainer = m_container;
}
return request;
}
catch
{
return null;
}
}
}
Aquí está mi uso habitual para eso. Agregue una copia estática a su clase de sitio base con todas las funciones de análisis que probablemente tenga:
protected static CookieWebClient wc = new CookieWebClient();
Y llámalo como tal:
public HtmlDocument Download(string url)
{
HtmlDocument hdoc = new HtmlDocument();
HtmlNode.ElementsFlags.Remove("option");
HtmlNode.ElementsFlags.Remove("select");
Stream read = null;
try
{
read = wc.OpenRead(url);
}
catch (ArgumentException)
{
read = wc.OpenRead(HttpHelper.HTTPEncode(url));
}
hdoc.Load(read, true);
return hdoc;
}
La otra razón principal por la que puede estar fallando es que el servidor está cerrando la conexión ya que ha tenido una conexión abierta durante demasiado tiempo. Puede probar esto agregando un try catch alrededor de la parte de descarga como se indicó anteriormente y, si falla, reinicie el cliente web e intente descargarlo nuevamente:
HtmlDocument d = new HtmlDocument();
try
{
d = this.Download(prp.PropertyUrl);
}
catch (WebException e)
{
this.Msg(Site.ErrorSeverity.Severe, "Error connecting to " + this.URL + " : Resubmitting..");
wc = new CookieWebClient();
d = this.Download(prp.PropertyUrl);
}
Esto me salva el culo todo el tiempo, incluso si fue el servidor el que te rechazó, esto puede reorganizar el lote. Las cookies se borran y puedes recorrer libremente. Si lo peor realmente empeora, agregue soporte proxy y obtenga un nuevo proxy por cada solicitud de 50 ish.
Eso debería ser más que suficiente para patear el tuyo y el de cualquier otro sitio.
¡METIDO!