2010-05-21 29 views
5

¿Cuál es la mejor manera de tomar una cadena de HTML y convertirlo en algo útil?C# análisis sintáctico de HTML para uso general?

Básicamente, si tomo una URL y obtengo el HTML de esa URL en .net, recibo una respuesta, pero esto vendría en la forma de un archivo, secuencia o cadena.

¿Qué sucede si quiero un documento real o algo que pueda rastrear como un objeto XmlDocument?

Tengo algunas ideas y una solución ya implementada sobre esto, pero estoy interesado en ver qué piensa la comunidad al respecto.

+1

¿Por qué no utilizar las bibliotecas .NET para el análisis de XML? – Joren

+0

lol No puedo creer que hayas dicho eso ... html no es xml, ciertas cosas que hacen que html sea válido no son xml válidas, esto no funcionará. – War

Respuesta

3

Uso la aplicación mshtml.

simplemente consulte el ensamblaje mshtml y luego incluya el espacio de nombres.

desde allí se puede declarar un objeto HTMLDocument que es consultable, es un poco dolor de cabeza en algunos lugares porque el diseño de la API te obliga a hacer coladas al azar pero hace el trabajo y siempre se puede poner en una utilidad clase por sí mismo, por lo que no tiene que mantener sus rarezas en las principales clases de código de la aplicación.

7

Las páginas HTML rara vez son válidas en XML, incluso si están escritas en XHTML, por lo que no se pueden cargar en un objeto XML estándar.

Eche un vistazo a HTML Agility Pack. Este componente .net le permitirá recorrer el DOM incluso si no es válido.

+0

Es por eso que dije "como un documento xml" como en similar a ... Lo sé muy bien. – War

1
var browser = new System.Windows.Forms.WebBrowser(); 
browser.Navigate(new System.Uri("http://example.com")); 
var doc = browser.Document; 

HtmlDocument tiene una serie de útil members

Por ejemplo, doc.All que es HtmlControlCollection que puede convertirse en una colección genérica ICollection<HtmlControl>.

HtmlControl.DomElement se refiere al espacio de nombre mshtml mencionado en otra respuesta.

Algunos ejemplo de uso se pueden encontrar en the source of this project

+0

simple ... muy simple ...pero intente esto ... 1. Cree una nueva aplicación de consola 2. Ponga ese código en él 3. agregue una referencia a System.Windows.Forms 4. Ejecútelo. Este ejemplo parece romperse, utilizando la API mshtml, pero no estoy seguro del paquete de agilidad. – War

+0

@Wardy: El control WebBrowser no funciona en la aplicación de la consola porque es un contenedor en el objeto COM que no se puede ejecutar en modo STA – abatishchev

+0

Exactamente, tengo un código que funciona como parte de un ensamblaje independiente, simplemente me refiero a él y uso si es necesario, la mejor solución es siempre una portátil agradable y limpia :) – War

1

La forma más fácil es para cargarlo en la clase System.Windows.Forms.HtmlDocument. A continuación, puede acceder al DOM desde allí.

Por supuesto, le conviene observar el tipo de contenido en la respuesta HTTP para determinar si esto es en realidad HTML (a lo que se refiere la pregunta) o si se trata de datos binarios, como una imagen.

HTTP simplemente escupe un documento sin formato que es o datos binarios o texto de marcado y el navegador generalmente hace el resto, usando las sugerencias que se proporcionan en el encabezado de respuesta. Esto, por supuesto, está muy bien envuelto en el clas de HTTPWebResponse, listo para usar.

+0

No me gusta tener esa dependencia de los formularios de Windows para un problema web, aunque técnicamente esta es la "manera más fácil", no es la más práctica ... ¿por qué introducir una dependencia no relevante? – War

3

Puede usar Tidy.net para formatear el html que obtiene en su respuesta. Luego podrá cargar eso en un XmlDocument y atravesar los nodos para obtener lo que desea.

Tidy document = new Tidy(); 
TidyMessageCollection messageCollection = new TidyMessageCollection(); 

document.Options.DocType = DocType.Omit; 
document.Options.Xhtml = true; 
document.Options.CharEncoding = CharEncoding.UTF8; 
document.Options.LogicalEmphasis = true; 

document.Options.MakeClean = false; 
document.Options.QuoteNbsp = false; 
document.Options.SmartIndent = false; 
document.Options.IndentContent = false; 
document.Options.TidyMark = false; 

document.Options.DropFontTags = false; 
document.Options.QuoteAmpersand = true; 
document.Options.DropEmptyParas = true; 

MemoryStream input = new MemoryStream(); 
MemoryStream output = new MemoryStream(); 
byte[] array = Encoding.UTF8.GetBytes(xmlResult); 
input.Write(array, 0, array.Length); 
input.Position = 0; 

document.Parse(input, output, messageCollection); 

string tidyXhtml = Encoding.UTF8.GetString(output.ToArray()); 

XmlDocument outputXml = new XmlDocument(); 
outputXml.LoadXml((tidyXhtml); 
+0

cualquier documentación detallada para este componente? – Smith

+0

Prueba el proyecto ordenado del que se deriva tidy.net. No .net, pero debería darle una idea del uso. http://tidy.sourceforge.net/ – skyfoot

+0

interesante pero eso es un montón de código para obtener un documento en un estado legible ¿no crees? ... no es tan malo si solo tienes que escribirlo una vez aunque supongo ... sin embargo, cuestionaría el rendimiento – War

Cuestiones relacionadas