Necesito una poderosa biblioteca web scraper para extraer contenidos de la web. Eso puede ser pagado o gratis ambos estarán bien para mí. Por favor sugiérame una biblioteca o una mejor forma de extraer los datos y almacenarlos en mi base de datos preferida. He buscado pero no encontré ninguna buena solución para esto. Necesito una buena sugerencia de expertos. Por favor, ayúdame.Necesito una poderosa biblioteca de Web Scraper
Respuesta
El raspado es fácil en realidad, solo tiene que analizar el contenido que está descargando y obtener todos los enlaces asociados.
La parte más importante es la parte que procesa el HTML. Debido a que la mayoría de los navegadores no requieren el código HTML más limpio (o compatible con los estándares) para poder representarlos, se necesita un analizador HTML que pueda dar sentido al HTML que no siempre está bien formado.
Te recomiendo que uses el HTML Agility Pack para este propósito. Lo hace muy bien en el manejo de HTML no bien formado, y proporciona una interfaz sencilla para que pueda usar consultas XPath para obtener nodos en el documento resultante.
Más allá de eso, solo necesita elegir un almacén de datos para almacenar sus datos procesados (puede usar cualquier tecnología de base de datos para eso) y una forma de descargar contenido de la web, que .NET proporciona dos mecanismos de alto nivel para , las clases WebClient y HttpWebRequest/HttpWebResponse.
Por favor, por el amor de. ¡No sugiera el uso de WebClient/HttpWebRequest/HttpWebResponse para alguien que necesite un raspador web Powerfull! Sería mejor simplemente escribir algunos enchufes y cargar todos los datos. – CodingBarfield
@Barfieldmv: No soy fanático de WebClient, ya que es de muy alto nivel, ya que Sockets IMO está por debajo del bajo nivel; te obliga a implementar un buen negocio solo para hacer solicitudes/respuestas, mientras que HttpWebRequest/HttpWebResponse tiene la mayor parte de la funcionalidad que uno necesitaría tener un rastreador algo inteligente integrado (soporte de cookies, colecciones de encabezado, etc., etc.). – casperOne
Supongo que esta es una publicación antigua, pero por el bien de la posteridad, comentaré: en nuestra aplicación, que imagino que ya no es atípica, tenemos que eliminar sitios que no solo requieren una sesión de inicio de sesión, sino que usan asincrónicos complicados JavaScript, que se activa cuando el usuario hace clic en algo, para cargar datos desde sus servidores, y cuando esas solicitudes se completan, pasa por un proceso de actualización del DOM. Raspado que es cualquier cosa menos fácil.Somos revendedores y algunos de nuestros mayoristas no proporcionarán ningún otro medio para obtener información sobre la disponibilidad del producto. (Increíble, pero cierto.) – Shavais
Mi consejo:
Se podría mirar a su alrededor para un analizador de HTML y luego utilizarlo para analizar la información de los sitios. (Como here). Entonces, todo lo que tendría que hacer es guardar esos datos en su base de datos como mejor le parezca.
He hecho mi propio raspador algunas veces, es bastante fácil y le permite personalizar los datos que se guardan.
herramientas de minería de datos
Si realmente desea conseguir una herramienta para hacer esto, entonces no debería tener ningún problema finding some.
Para sitios web simples (= solo html simple), Mechanize funciona muy bien y rápido. Para los sitios que usan Javascript, AJAX o incluso Flash, necesita una solución de navegador real como iMacros.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace SoftCircuits.Parsing
{
public class HtmlTag
{
/// <summary>
/// Name of this tag
/// </summary>
public string Name { get; set; }
/// <summary>
/// Collection of attribute names and values for this tag
/// </summary>
public Dictionary<string, string> Attributes { get; set; }
/// <summary>
/// True if this tag contained a trailing forward slash
/// </summary>
public bool TrailingSlash { get; set; }
/// <summary>
/// Indicates if this tag contains the specified attribute. Note that
/// true is returned when this tag contains the attribute even when the
/// attribute has no value
/// </summary>
/// <param name="name">Name of attribute to check</param>
/// <returns>True if tag contains attribute or false otherwise</returns>
public bool HasAttribute(string name)
{
return Attributes.ContainsKey(name);
}
};
public class HtmlParser : TextParser
{
public HtmlParser()
{
}
public HtmlParser(string html) : base(html)
{
}
/// <summary>
/// Parses the next tag that matches the specified tag name
/// </summary>
/// <param name="name">Name of the tags to parse ("*" = parse all tags)</param>
/// <param name="tag">Returns information on the next occurrence of the specified tag or null if none found</param>
/// <returns>True if a tag was parsed or false if the end of the document was reached</returns>
public bool ParseNext(string name, out HtmlTag tag)
{
// Must always set out parameter
tag = null;
// Nothing to do if no tag specified
if (String.IsNullOrEmpty(name))
return false;
// Loop until match is found or no more tags
MoveTo('<');
while (!EndOfText)
{
// Skip over opening '<'
MoveAhead();
// Examine first tag character
char c = Peek();
if (c == '!' && Peek(1) == '-' && Peek(2) == '-')
{
// Skip over comments
const string endComment = "-->";
MoveTo(endComment);
MoveAhead(endComment.Length);
}
else if (c == '/')
{
// Skip over closing tags
MoveTo('>');
MoveAhead();
}
else
{
bool result, inScript;
// Parse tag
result = ParseTag(name, ref tag, out inScript);
// Because scripts may contain tag characters, we have special
// handling to skip over script contents
if (inScript)
MovePastScript();
// Return true if requested tag was found
if (result)
return true;
}
// Find next tag
MoveTo('<');
}
// No more matching tags found
return false;
}
/// <summary>
/// Parses the contents of an HTML tag. The current position should be at the first
/// character following the tag's opening less-than character.
///
/// Note: We parse to the end of the tag even if this tag was not requested by the
/// caller. This ensures subsequent parsing takes place after this tag
/// </summary>
/// <param name="reqName">Name of the tag the caller is requesting, or "*" if caller
/// is requesting all tags</param>
/// <param name="tag">Returns information on this tag if it's one the caller is
/// requesting</param>
/// <param name="inScript">Returns true if tag began, and did not end, and script
/// block</param>
/// <returns>True if data is being returned for a tag requested by the caller
/// or false otherwise</returns>
protected bool ParseTag(string reqName, ref HtmlTag tag, out bool inScript)
{
bool doctype, requested;
doctype = inScript = requested = false;
// Get name of this tag
string name = ParseTagName();
// Special handling
if (String.Compare(name, "!DOCTYPE", true) == 0)
doctype = true;
else if (String.Compare(name, "script", true) == 0)
inScript = true;
// Is this a tag requested by caller?
if (reqName == "*" || String.Compare(name, reqName, true) == 0)
{
// Yes
requested = true;
// Create new tag object
tag = new HtmlTag();
tag.Name = name;
tag.Attributes = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
// Parse attributes
MovePastWhitespace();
while (Peek() != '>' && Peek() != NullChar)
{
if (Peek() == '/')
{
// Handle trailing forward slash
if (requested)
tag.TrailingSlash = true;
MoveAhead();
MovePastWhitespace();
// If this is a script tag, it was closed
inScript = false;
}
else
{
// Parse attribute name
name = (!doctype) ? ParseAttributeName() : ParseAttributeValue();
MovePastWhitespace();
// Parse attribute value
string value = String.Empty;
if (Peek() == '=')
{
MoveAhead();
MovePastWhitespace();
value = ParseAttributeValue();
MovePastWhitespace();
}
// Add attribute to collection if requested tag
if (requested)
{
// This tag replaces existing tags with same name
if (tag.Attributes.ContainsKey(name))
tag.Attributes.Remove(name);
tag.Attributes.Add(name, value);
}
}
}
// Skip over closing '>'
MoveAhead();
return requested;
}
/// <summary>
/// Parses a tag name. The current position should be the first character of the name
/// </summary>
/// <returns>Returns the parsed name string</returns>
protected string ParseTagName()
{
int start = Position;
while (!EndOfText && !Char.IsWhiteSpace(Peek()) && Peek() != '>')
MoveAhead();
return Substring(start, Position);
}
/// <summary>
/// Parses an attribute name. The current position should be the first character
/// of the name
/// </summary>
/// <returns>Returns the parsed name string</returns>
protected string ParseAttributeName()
{
int start = Position;
while (!EndOfText && !Char.IsWhiteSpace(Peek()) && Peek() != '>' && Peek() != '=')
MoveAhead();
return Substring(start, Position);
}
/// <summary>
/// Parses an attribute value. The current position should be the first non-whitespace
/// character following the equal sign.
///
/// Note: We terminate the name or value if we encounter a new line. This seems to
/// be the best way of handling errors such as values missing closing quotes, etc.
/// </summary>
/// <returns>Returns the parsed value string</returns>
protected string ParseAttributeValue()
{
int start, end;
char c = Peek();
if (c == '"' || c == '\'')
{
// Move past opening quote
MoveAhead();
// Parse quoted value
start = Position;
MoveTo(new char[] { c, '\r', '\n' });
end = Position;
// Move past closing quote
if (Peek() == c)
MoveAhead();
}
else
{
// Parse unquoted value
start = Position;
while (!EndOfText && !Char.IsWhiteSpace(c) && c != '>')
{
MoveAhead();
c = Peek();
}
end = Position;
}
return Substring(start, end);
}
/// <summary>
/// Locates the end of the current script and moves past the closing tag
/// </summary>
protected void MovePastScript()
{
const string endScript = "</script";
while (!EndOfText)
{
MoveTo(endScript, true);
MoveAhead(endScript.Length);
if (Peek() == '>' || Char.IsWhiteSpace(Peek()))
{
MoveTo('>');
MoveAhead();
break;
}
}
}
}
}
- 1. Hows Mozenda Screen Scraper codificado?
- 2. ¿Hay un C++ Wrapper amigable STL y UTF-8 para ICU u otra poderosa biblioteca Unicode?
- 3. Necesito la biblioteca de modbus Java
- 4. ¿Cuál es el significado de {} en la gramática de Web :: Scraper?
- 5. Libtool solo crea una biblioteca estática - Necesito objetos compartidos
- 6. biblioteca estática, pero aún necesito encabezados?
- 7. Necesito biblioteca C que implementa operaciones de conjunto
- 8. Pequeña biblioteca de navegador web portátil?
- 9. F # biblioteca del servidor web
- 10. ¿Hay una biblioteca estándar de iconos abiertos para desarrolladores web?
- 11. Explorador web programático Biblioteca Java
- 12. Con C++ 11, ¿todavía necesito una biblioteca de manipulación de cadenas no estándar para texto Unicode?
- 13. ¿Cómo averiguo qué espacio de nombres necesito importar de una biblioteca java?
- 14. ¿Necesito un nuevo archivo de claves .snk para cada versión de una biblioteca con nombre fuerte?
- 15. Necesito una biblioteca de cliente de java stomp que funcione con ssl
- 16. ASP.NET Web Garden: ¿cuántos procesos de trabajo necesito?
- 17. ¿Cómo hacer que una consulta de búsqueda SQL sea más poderosa?
- 18. Una poderosa herramienta de administración para MySQL con características similares a SQL Server Management studio
- 19. necesito un navegador web en mi aplicación de escritorio
- 20. ¿Cómo necesito una versión específica de una gema de rubí?
- 21. Si utilizo una biblioteca de tipos (.tlb) en un proyecto VB6, ¿necesito distribuirlo con .exe?
- 22. Necesito una biblioteca C++ para ajustar las curvas a los puntos de datos
- 23. ¿Realmente necesito una capa de servicio?
- 24. ¿Qué archivos necesito registrar después de agregar una referencia de servicio web?
- 25. apariencia UIBarButtonItem Necesito una excepción
- 26. ¿Meteor es una opción, si necesito una API REST adicional?
- 27. ¿Convertir una biblioteca estática a una biblioteca compartida?
- 28. Biblioteca de control de usuario web de ASP.NET
- 29. Necesito un algoritmo de coincidencia de direcciones
- 30. Consumir una referencia web en una biblioteca de clases (C# /. NET)
Solo una palabra de advertencia: al raspar contenido, el sitio que se está raspando puede cambiar drásticamente su HTML sin previo aviso. Un día tienes contenido donde lo esperas; al día siguiente reemplazaron una tabla HTML con un DIV o algo así. Es una buena idea contar con un plan de contingencia y poder modificar rápidamente cómo y qué está raspando. –