Diagrama del juego de filosofía de Wikipedia en Python y R


Así que soy relativamente nuevo en Python, y para aprender, comencé a escribir un programa que se conecta a wikipedia, encuentra el primer enlace en la sección de descripción general de un artículo aleatorio, sigue ese enlace y continúa hasta que ingresa a un bucle o encuentra la página de filosofía (como se detalla aquí) y luego repite este proceso para un nuevo artículo aleatorio un número específico de veces. Luego quiero recopilar los resultados en alguna forma de estructura de datos útil, para poder pasar los datos a R usando el Biblioteca rpy para poder dibujar algún tipo de diagrama de red (R es bastante bueno para dibujar cosas así) con cada nodo en el diagrama que representa las páginas visitadas y las flechas que toman las rutas desde el artículo inicial hasta la página de filosofía.

Así que no tengo problemas para que Python devuelva el html bastante estructurado de la wiki, pero hay algunos problemas que no puedo resolver. Hasta ahora he seleccionado el primer enlace usando un cssselector de la biblioteca lxml. Selecciona el primer enlace (en una etiqueta a) que es un descendiente directo de la etiqueta ap, que es un descendiente directo de una etiqueta div con class = "mw-content-ltr" de esta manera:

    user_agent = 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT)'
    values = {'name' : 'David Kavanagh',
      'location' : 'Belfast',
      'language' : 'Python' }
    headers = { 'User-Agent' : user_agent }
    encodes = urllib.urlencode(values)
    req = urllib2.Request(url, encodes, headers)
    page = urllib2.urlopen(req)
    root = parse(page).getroot()
    return root.cssselect("div.mw-content-ltr>p>a")[0].get('href')

Este código reside en una función que utilizo para encontrar el primer enlace en la página. Funciona en su mayor parte, pero el problema es que si el primer enlace está dentro de alguna otra etiqueta en lugar de ser un descendiente directo de una etiqueta ap como, digamos, una etiqueta ab o algo así, entonces lo extraño. Como puede ver en el artículo de wiki anterior, los enlaces en cursiva o entre paréntesis no son elegibles para el juego, lo que significa que nunca obtengo un enlace en cursiva (bueno) pero con frecuencia obtengo enlaces que están entre paréntesis (malo) y a veces pierdo el primer enlace en una página como el primer enlace en el artículo de la Cátedra, que es taburete, pero está en negrita, así que no lo entiendo. He intentado eliminar la estipulación de descendiente directo, pero con frecuencia obtengo enlaces que están "encima" de la sección de descripción general, que generalmente están en el cuadro lateral, en la etiqueta ap, en una tabla, en el mismo div que la sección de descripción general.

Entonces la primera parte de mi pregunta es:

¿Cómo podría usar cssselectors o alguna otra función o biblioteca para seleccionar el primer enlace en la sección de descripción general que no está entre paréntesis o en cursiva? Pensé en usar expresiones regulares para mirar a través del html sin procesar, pero parece una solución muy torpe y pensé que podría haber algo un poco más agradable en el que no había pensado.

Entonces, actualmente estoy almacenando los resultados en una lista de listas. Entonces tengo una lista llamada rutas, en la que hay listas que contienen cadenas que contienen el título del artículo wiki.

La segunda parte de la pregunta es: ¿Cómo puedo recorrer esta lista de listas para representar las múltiples rutas convergentes? ¿Es una buena idea almacenar los resultados de esta manera? Dado que el diagrama final debería verse como un árbol al revés, pensé en hacer algún tipo de clase de árbol, pero eso parece mucho trabajo para algo que es conceptualmente bastante simple.

Cualquier idea o sugerencia sería muy apreciada.
Aclamaciones,
Davy

preguntado el 08 de noviembre de 11 a las 12:11

¡No publique dos preguntas diferentes en una! -

Beautiful Soup puede analizar HTML mejor (IMO). Un objeto BS tiene atributos (en sentido orientado a objetos) que devolverían etiquetas anidadas así como atributos (en sentido de etiqueta HTML) de la etiqueta. Debería ser un juego de niños. No vez usar expresiones regulares para analizar HTML stackoverflow.com/questions/1732348/… -

2 Respuestas

Solo responderé la segunda pregunta:

Para empezar, simplemente mantenga un dict mapeando un título de artículo de Wikipedia al siguiente. Esto hará que sea más fácil y rápido comprobar si has llegado a un artículo que ya has encontrado antes. Básicamente, esto es solo almacenar los vértices de un gráfico dirigido, indexados por sus orígenes.

Si llega al punto en que un dictado de Python no es lo suficientemente eficiente (tiene una sobrecarga de memoria significativa, una vez que tiene millones de elementos, la memoria puede ser un problema), puede encontrar una estructura de datos de gráficos más eficiente que se adapte a sus necesidades.

EDITAR

Ok, también responderé la primera pregunta ...

Para la primera parte, recomiendo encarecidamente utilizar el API de MediaWiki en lugar de obtener la versión HTML y analizarla. La API permite consultar ciertos tipos de enlaces, por ejemplo, solo enlaces entre wiki o solo enlaces entre idiomas. Además, hay Bibliotecas cliente de Python para esta API, lo que debería facilitar su uso desde el código Python.

¡No analice el HTML de un sitio web si proporciona una API completa y bien documentada!

respondido 08 nov., 11:22

Toda la wikipedia en inglés tiene menos de 4 millones de artículos. Puede crear un prototipo insertando 4M cadenas aleatorias de 50 bytes en un hash solo para verificar si el intérprete lo manejará fácilmente. - Tadeusz A. Kadłubowski

Para la primera parte, no es posible encontrar corchetes con selectores css, porque en lo que respecta al html, los corchetes son solo texto.

Si yo fuera usted, usaría selectores para encontrar todos los elementos de párrafo relevantes que son válidos para el juego. Luego, buscaría en el texto del elemento de párrafo y eliminaría cualquiera que no sea válido, por ejemplo, cualquier cosa entre corchetes y cualquier cosa entre etiquetas en cursiva. Luego buscaría en este texto procesado los elementos de enlace que necesito. Esto es un poco más agradable que procesar manualmente todo el documento html.

No estoy seguro de seguir exactamente lo que está haciendo para la segunda parte, pero en cuanto a representar los resultados de esta búsqueda como un árbol: esta es una mala idea ya que está buscando ciclos que los árboles no pueden representar.

Para una estructura de datos, tendría listas de 'nodos', donde un nodo representa una página y tiene una URL y un recuento de ocurrencias. Luego usaría un algoritmo de fuerza bruta para comparar listas de nodos; si las dos listas tienen un nodo que es el mismo, puede fusionarlos, aumentando el recuento de 'ocurrencias' para cada nodo reflejado.

No usaría la 'lista' estándar de Python, ya que no se puede repetir sobre sí misma. Tal vez cree su propia implementación de lista vinculada para contener los nodos.

respondido 08 nov., 11:16

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.