La mejor forma de volver a usar el poder de lxml después de tener que utilizar una expresión regular para buscar algo en un documento html

StackOverflow https://stackoverflow.com/questions/2421396

Pregunta

Estoy tratando de extraer texto de un gran número de documentos html (los números en los cientos de miles).Los documentos son realmente formas, pero son preparados por un grupo muy grande de diferentes organizaciones así que hay una significativa variación en la forma de crear el documento.Por ejemplo, los documentos están divididos en capítulos.Yo podría extraer el contenido del Capítulo 5 de cada documento, por lo que se puede analizar el contenido del capítulo.Inicialmente pensé que esto iba a ser fácil, pero resulta que los autores podrían utilizar un conjunto de no-tablas anidadas en todo el documento para mantener el contenido de lo que el Capítulo n se podría mostrar el uso de etiquetas td dentro de una tabla.O se podría usar otros elementos como el p etiquetas H etiquetas, etiquetas div o cualquier otro elemento de nivel de bloque.

Después de intentar varias veces para uso lxml para que me ayude a identificar el comienzo y el final de cada capítulo he decidido que es mucho más limpia, para utilizar una expresión regular debido a que en cada caso, no importa lo que la encierra un elemento html es el capítulo de la etiqueta siempre es en forma de

>Chapter #

Es un poco más complicado, en que podría haber algún espacio en blanco o no separación espacio representado de diferentes maneras ( o espacios).Sin embargo era trivial para escribir una expresión regular para identificar el comienzo de cada sección.(El comienzo de una sección es el final de la sección anterior.)

Pero ahora quiero usar lxml para obtener el texto.Mi pensamiento es que tengo realmente ninguna opción pero para caminar a lo largo de mi cuerda para encontrar el cierre de etiqueta para el elemento que encierra el texto que estoy utilizando para encontrar la sección correspondiente.

Que está aquí es un ejemplo de que el elemento de retención el nombre del Capítulo es un div

<div style="DISPLAY: block; MARGIN-LEFT: 0pt; TEXT-INDENT: 0pt; MARGIN-RIGHT: 0pt" align="left"><font style="DISPLAY: inline; FONT-WEIGHT: bold; FONT-SIZE: 10pt; FONT-FAMILY: Times New Roman">Chapter 1.&#160;&#160;&#160;Our Beginnings.</font></div>

Así que me estoy imaginando que iba a comenzar en el lugar donde me encontré con el partido por el capítulo 1 y configurar una de las expresiones regulares para buscar la siguiente

</div|</td|</p|</h1 . . .

Así que en este punto he identificado el tipo de elemento de la celebración de mi título de capítulo

Puedo usar la misma lógica para encontrar todo el texto que está dentro de ese elemento que es crear una expresión regular para que me ayude marca de

>Chapter 1.&#160;&#160;&#160;Our Beginnings.<

Así que he identificado donde mi Capítulo 1 comienza

Yo puedo hacer lo mismo para el capítulo 2 (que es donde el Capítulo 1 termina)

Ahora me estoy imaginando que me voy a cortar el documento, comenzando por la apertura del elemento que me ha identificado como el elemento indica el lugar en el capítulo 1 comienza y termina justo antes de la apertura del elemento que me ha identificado como el elemento que indica el lugar en el Capítulo 2 comienza.La cadena que he identificado luego de ser alimentados a lxml a utilizar su poder para obtener el contenido.

Voy a todos los de este problema porque he leído una y otra vez - nunca utilizar una expresión regular para extraer el contenido de los documentos html y no me he golpeado en una manera de ser lo más preciso con lxml para identificar el inicio y final de las localizaciones para el texto que se desea extraer.Por ejemplo, nunca se puede estar seguro de que el subtítulo del Capítulo 1 es Nuestro principio podría ser Nuestra Roja Canarias.Permítanme decir que me pasé dos días seguidos intentando con lxml a ser convencido de que tenía el principio y final de los elementos y sólo podía ser exactos <El 60% del tiempo, pero muy poco de la expresión regular que me ha dado más de un 95% de éxito.

Tengo una tendencia a hacer las cosas más complicadas de lo necesario, así que me estoy preguntando si alguien ha visto o resuelto problemas similares y si tenían un enfoque (no los detalles de la mente) que les gustaría ofrecer.

¿Fue útil?

Solución 3

Como temía que no hay manera sistemática a utilizar lxml para identificar y extraer lo que necesito. O bien h aprecio todos repican en. Nota-esto no es culpa de lxml, es el fallo de la codificación html inconsistente. Por ejemplo. Debido a que un capítulo es una división razonable de un documento de todo el contenido de un capítulo debe ser envuelto en algún tipo de elemento. Probablemente el más flexible sería una etiqueta div con el div subsecuente ser el siguiente capítulo. Esto haría un capítulo de una rama del árbol. Por desgracia, mientras que aproximadamente el 20% de los documentos podría estar bien estructurado que los otros no lo son.

Me podría poner a prueba para cada tipo de elemento que debe mantener el contenido de mi (div, p) y apoderarse de todos sus hijos y todos sus hermanos hasta que llegue al siguiente elemento de ese tipo que tiene información que me alerta que están en el extremo de la sección (comienzo de la siguiente sección). Pero esto parece demasiado trabajo cuando estoy bien 95% de las veces o más con una expresión regular.

Gracias por todas las respuestas y los comentarios como siempre learnded de ellos.

Otros consejos

A veces no hay un camino directo para llegar el contenido a la hora de tratar con el mal o de forma incoherente escrito en HTML.

Es posible que desee buscar en el uso de lince o de uno de los navegadores basados en texto para volcar el contenido de la página, ya sea en un archivo, o a la tubería en el código y, a continuación, el proceso de la misma.O bien, puede utilizar lxml para cargar y analizar la página, a continuación, extraer el texto mediante text_content() e ir después de los capítulos a través de expresiones regulares.

Como ellos dicen, GIGO - entra basura, sale basura, y es nuestro trabajo como desarrolladores de spin que la basura en oro.Hacerlo puede obtener bastante desordenado.

Lo más sencillo que suena como lo que pueda hacer es iterar sobre tree.getroot (). Iterdescendants () en busca de un nodo con node.text que coincide con la expresión regular deseada. A partir de ahí, se puede pasar el nodo a una función que utiliza algunas heurísticas ad-hoc para determinar dónde está el texto. (Tal vez si iterdescendants en la raíz es demasiado lento puede utilizar el enfoque de expresiones regulares y sumergirse en etree para tratar de encontrar una función f(text_position) -> node.)

Por ejemplo, si usted encuentra que el objetivo era un //tr/td, puede pasar a alguna subrutina tabla de conversión de texto que parecía encontrar en la siguiente anotación en node.parent () para ver si tiene texto que tenga sentido ( aproximadamente el capítulo de longitud, que contiene ciertas palabras, lo que sea). Del mismo modo, se puede compensar algunas heurísticas para encontrar los datos en otras etiquetas como div y p. Si usted se encuentra en una etiqueta desconocida como font puede probar burbujeando un número limitado de niveles de encontrar algo que usted sabe cómo manejar - hay que ser cautos a la burbuja no demasiado lejos, o me imagino que podría recuperar accidentalmente texto de otro capítulo.

El quid de la cuestión parece ser que está minería de datos que no está presentada mediante programación en una manera programática -. En estos casos, la interacción humana suele ser necesario un cierto grado

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top