2008-11-18 23 views
19

He guardado el html de toda una página web en una cadena, y ahora Quiero obtener los valores "href" de los enlaces, preferiblemente con la posibilidad de guardarlos en diferentes cadenas más adelante. ¿Cuál es la mejor manera de hacer esto?C# - ¿El mejor enfoque para analizar páginas web?

He intentado guardar la cadena como un documento .xml y analizarla usando un navegador XPathDocument, pero (sorpresa sorpresa) no navega demasiado bien en un documento que no sea realmente un xml.

¿Son las expresiones regulares la mejor manera para lograr lo que estoy tratando de lograr?

Respuesta

10

Las expresiones regulares son una forma de hacerlo, pero pueden ser problemáticas.

La mayoría de las páginas HTML no se pueden analizar utilizando técnicas html estándar porque, como ya descubrió, la mayoría no valida.

Puede pasar el tiempo tratando de integrar HTML Tidy o una herramienta similar, pero sería mucho más rápido construir la expresión regular que necesita.

ACTUALIZACIÓN

En el momento de esta actualización que he recibido 15 y 9 downvotes. Creo que tal vez la gente no está leyendo la pregunta ni los comentarios sobre esta respuesta. Todo lo que OP quería hacer era tomar los valores href. Eso es todo. Desde esa perspectiva, una expresión regular simple está bien. Si el autor hubiera querido analizar otros elementos, entonces no hay forma de que recomiende la expresión regular como dije al principio, en el mejor de los casos es problemática.

+0

Buena respuesta - expresiones regulares es su amigo! –

+23

Mala respuesta. No hagas esto – SLaks

+8

-1 Hmmm, usando Regex para analizar HTML. ¿Qué podría salir mal? Oh, eso es correcto: http://stackoverflow.com/questions/1732348/regex-match-open-tags-except-xhtml-self-contained-tags – Ash

0

Puede tener más suerte usando xml si sabe o puede arreglar el documento para que esté al menos bien formado. Si tiene buena html (o más bien, xhtml), el sistema xml en .Net debería ser capaz de manejarlo. Lamentablemente, un buen html es extremadamente raro.

Por otro lado, las expresiones regulares son realmente malas al analizar html. Afortunadamente, no necesita manejar una especificación html completa. Todo lo que necesita para preocuparse es analizar href= cadenas para obtener la url. Incluso esto puede ser complicado, así que no intentaré hacerlo de inmediato. En cambio, comenzaré haciendo algunas preguntas para intentar establecer algunas reglas básicas. Básicamente todos se reducen a "¿Cuánto sabes sobre el documento?", Pero aquí va:

  • ¿Sabes si el texto "href" siempre estará en minúsculas?
  • ¿Sabes si siempre usará comillas dobles, comillas simples o nada en la URL?
  • ¿Es siempre una URL válida, o necesita dar cuenta de cosas como '#', declaraciones de JavaScript y similares?
  • ¿Es posible trabajar con un documento donde el contenido describe características html (IE: href= también podría estar en el documento y no pertenecer a una etiqueta de anclaje)?
  • ¿Qué más puede decirnos acerca del documento?
+0

Sé que el texto href siempre será en minúsculas. Siempre usará comillas dobles. Puede o no ser siempre una URL válida, pero asumo que será el 99% del tiempo. El documento tiene una posibilidad de tener "href" en otro lugar. Eso es todo lo que puedo pensar. ¿Sería una función de análisis realmente mejor que la expresión regular? – MattSayar

+0

El asesino aquí está permitiendo href = en otro lugar. Te envía de vuelta a la búsqueda de una etiqueta de ancla real, y eso significa que es mejor utilizar una biblioteca de análisis (muy indulgente). Incluso podría intentar cargarlo en un control de navegador web. –

2

Probablemente usted quiere algo así como el analizador Majestic: http://www.majestic12.co.uk/projects/html_parser.php

Hay algunas otras opciones que pueden hacer frente a html escamosa, también. El paquete Html Agility vale la pena, como alguien más mencionó.

No creo que las expresiones regulares sean una solución ideal para HTML, ya que HTML no está libre de contexto. Probablemente produzcan un resultado adecuado, aunque impreciso; incluso la identificación determinista de un URI es un problema complicado.

1

Estoy de acuerdo con Chris Lively, porque el HTML a menudo no está muy bien formado, probablemente seas mejor con una expresión regular para esto.

href=[\"\'](http:\/\/|\.\/|\/)?\w+(\.\w+)*(\/\w+(\.\w+)?)*(\/|\?\w*=\w*(&\w*=\w*)*)?[\"\'] 

De here en RegExLib debe empezar

+0

Gracias Tiempo. Estoy intentando usar esto, sin embargo, C# me sigue diciendo que todas las barras invertidas son "secuencias de escape no reconocidas". Lanzar un @ no ayuda tampoco. ¿Sabes lo que está pasando? – MattSayar

+0

Hahah, quise decir "Gracias TIM". El tiempo no merece ningún agradecimiento. – MattSayar

+0

Este enlace me ayudó a resolverlo http://regexadvice.com/forums/thread/36529.aspx – MattSayar

5

Para hacer frente a HTML de todas las formas y tamaños Yo prefiero usar el paquete de HTMLAgility @http://www.codeplex.com/htmlagilitypack que le permite escribir XPaths contra los nodos que desee y obtener los regresar en una colección.

+0

+1 paquete increíble! ¡realmente hizo mi vida MUCHO más fácil! –

45

Puedo recomendar el HTML Agility Pack. Lo he usado en algunos casos donde necesitaba analizar HTML y funciona muy bien. Una vez que cargue su HTML en él, puede usar las expresiones XPath para consultar el documento y obtener sus etiquetas de anclaje (y casi cualquier otra cosa).

HtmlDocument yourDoc = // load your HTML; 
int someCount = yourDoc.DocumentNode.SelectNodes("your_xpath").Count; 
+1

Y es realmente fácil de usar. –

+0

wow, eso es maravilloso ... :) Iba a escribir un Analizador de HTML ... pero ahora ya no necesito hacerlo ... muchas gracias Jeff –

2

Siempre es mejor, si es posible, no redescubrir la rueda. Existen algunas buenas herramientas que, o bien convertir HTML a XML bien formado, o actuar como un XmlReader:

Aquí hay tres buenas herramientas:

  1. TagSoup, un programa de código abierto, es un Java y SAX - herramienta basada en, desarrollada por John Cowan. Esto es un analizador compatible con SAX escrito en Java que, en lugar de analizar XML bien formado o válido, analiza HTML como se lo encuentra en estado salvaje: pobre, desagradable y brutal, aunque a menudo lejos de ser corto. TagSoup está diseñado para personas que tienen que procesar este material utilizando una apariencia de diseño de aplicación racional. Al proporcionar una interfaz SAX, permite que las herramientas XML estándar se apliquen incluso al peor HTML. TagSoup también incluye un procesador de línea de comandos que lee archivos HTML y puede generar HTML limpio o XML bien formado que es una aproximación cercana a XHTML.
    Taggle es un puerto comercial C++ de TagSoup.

  2. SgmlReader es una herramienta desarrollada por Microsoft Chris Lovett.
    SgmlReader es una API de XmlReader sobre cualquier documento SGML (incluido el soporte integrado para HTML). También se proporciona una utilidad de línea de comandos que genera el resultado XML bien formado.
    Descargar el archivo zip que incluye el ejecutable independiente y el código fuente completo: SgmlReader.zip

  3. un logro excepcional se the pure XSLT 2.0 Parser of HTML escrito por David Carlisle.

Leer su código sería un gran ejercicio de aprendizaje para todos nosotros.

partir de la descripción:

"d: htmlparse (cadena)
  d: htmlparse (cadena, espacio de nombres, html-mode)

    La única forma de argumento es equivalente a)
    d: htmlparse (cadena, 'http://ww.w3.org/1999/xhtml', true()))

    Divide la cadena como HTML y/o XML usando algunas heurísticas incorporadas a)
    control implica apertura y cierre de elementos.

    No tiene pleno conocimiento de HTML DTD pero sí que tiene la lista completa de
    elementos vacíos y la lista completa de definiciones de entidades. Se aceptan entidades HTML y
    referencias de caracteres hexadecimales y hexadecimales. Nota html-entities
    se reconocen incluso si html-mode = false().

nombres     Element serán minúsculas (si html-modo es cierto()) y se colocan en el espacio de nombres
    especificado por el parámetro de espacio de nombres (que puede ser "" para denotar
    no-espacio de nombres a menos que el entrada ha eXPLICT declaraciones de espacios de nombres, en
    cuyo caso éstos serán honrados.

    nombres de los atributos serán minúsculas si html-mode = true()
"

Lea una descripción más detallada here.

Espero que esto haya ayudado.

Saludos,

Dimitre Novatchev.

Cuestiones relacionadas