2009-09-08 24 views
7

Estoy tratando de hacer un web scraper que analizará una página web de publicaciones y extraerá los autores. La estructura del esqueleto de la página web es la siguiente:Web scraping de Python que implica etiquetas HTML con atributos

<html> 
<body> 
<div id="container"> 
<div id="contents"> 
<table> 
<tbody> 
<tr> 
<td class="author">####I want whatever is located here ###</td> 
</tr> 
</tbody> 
</table> 
</div> 
</div> 
</body> 
</html> 

He estado tratando de utilizar BeautifulSoup y lxml hasta el momento de realizar esta tarea, pero no estoy seguro de cómo manejar las dos etiquetas div y etiqueta td porque tienen atributos. Además de esto, no estoy seguro de si debería confiar más en BeautifulSoup o lxml o una combinación de ambos. ¿Que debería hacer?

Por el momento, mi código es similar a lo que está abajo:

import re 
    import urllib2,sys 
    import lxml 
    from lxml import etree 
    from lxml.html.soupparser import fromstring 
    from lxml.etree import tostring 
    from lxml.cssselect import CSSSelector 
    from BeautifulSoup import BeautifulSoup, NavigableString 

    address='http://www.example.com/' 
    html = urllib2.urlopen(address).read() 
    soup = BeautifulSoup(html) 
    html=soup.prettify() 
    html=html.replace('&nbsp', '&#160') 
    html=html.replace('&iacute','&#237') 
    root=fromstring(html) 

que darse cuenta de que muchas de las declaraciones de importación puede ser redundante, pero me acaba de copiar cualquier momento que tuve en más archivo de origen.

EDITAR: Supongo que no dejé esto muy claro, pero tengo varias etiquetas en la página que quiero raspar.

Respuesta

11

No me queda claro por su pregunta por qué tiene que preocuparse por los div etiquetas - ¿Qué hay de hacer precisamente:

soup = BeautifulSoup(html) 
thetd = soup.find('td', attrs={'class': 'author'}) 
print thetd.string 

En el código HTML que das, la ejecución de este emite exactamente:

####I want whatever is located here ### 

que parece ser lo que quieres. Tal vez puedas especificar mejor qué es exactamente lo que necesitas y este fragmento súper simple no funciona: varias etiquetas td todas de la clase author que debes considerar (¿todas? ¿Algunas? ¿Cuáles?), Posiblemente omitiendo alguna tal etiqueta (qué quieres hacer en ese caso), y similares. Es difícil deducir exactamente cuáles son sus especificaciones, solo a partir de este ejemplo simple y código sobreabundante ;-).

Editar: si, de acuerdo con el comentario de la última OP, hay múltiples tales etiquetas td, uno por autor:

thetds = soup.findAll('td', attrs={'class': 'author'}) 
for thetd in thetds: 
    print thetd.string 

... es decir, no mucho más difícil en absoluto -)

+0

Gracias, Alex. Tengo varios autores en la página, por lo que tendré varias etiquetas td. ¿Cómo puedo iterar sobre cada uno de ellos? – GobiasKoffi

1

BeautifulSoup es ciertamente el analizador/analizador de HTML canónico. Pero si tiene que coincidir con este tipo de fragmento, en lugar de construir todo un objeto jerárquico que represente HTML, pyparsing facilita la definición de etiquetas HTML iniciales y finales como parte de la creación de una expresión de búsqueda más grande:

from pyparsing import makeHTMLTags, withAttribute, SkipTo 

author_td, end_td = makeHTMLTags("td") 

# only interested in <td>'s where class="author" 
author_td.setParseAction(withAttribute(("class","author"))) 

search = author_td + SkipTo(end_td)("body") + end_td 

for match in search.searchString(html): 
    print match.body 

La función makeHTMLTags de Pyparsing hace mucho más que simplemente emitir expresiones "<tag>" y "</tag>".También maneja:

  • sin vaina juego de etiquetas de
  • "<tag/>" sintaxis
  • cero o más atributos en la etiqueta de apertura
  • atributos definidos en orden arbitrario
  • nombres de atributo con espacios de nombres
  • valores de atributo en comillas simples, dobles o sin comillas
  • espacios en blanco intervinientes entre la etiqueta y los símbolos, o el nombre del atributo, '=', una valor d
  • atributos son accesibles después de analizar los resultados como el nombre

Estos son los errores más comunes cuando se considera el uso de una expresión regular para el raspado de HTML.

6

o usted podría estar usando pyquery, ya BeautifulSoup no se mantiene de forma activa más, ver http://www.crummy.com/software/BeautifulSoup/3.1-problems.html

primero, instale pyquery con

easy_install pyquery 

continuación, la secuencia de comandos podría ser tan simple como

from pyquery import PyQuery 
d = PyQuery('http://mywebpage/') 
allauthors = [ td.text() for td in d('td.author') ] 

pyquery usa la sintaxis del selector css familiar de jQuery que me parece más intuitiva que la de BeautifulSoup. Utiliza lxml debajo, y es mucho más rápido que BeautifulSoup. Pero BeautifulSoup es pura python, y por lo tanto también funciona en el motor de aplicaciones de Google

5

La biblioteca lxml es ahora el estándar para analizar html en python. La interfaz puede parecer incómoda al principio, pero es muy útil para lo que hace.

Debería dejar que la libary maneje la especialidad xml, como las entidades escapadas y las entidades;

import lxml.html 

html = """<html><body><div id="container"><div id="contents"><table><tbody><tr> 
      <td class="author">####I want whatever is located here, eh? &iacute; ###</td> 
      </tr></tbody></table></div></div></body></html>""" 

root = lxml.html.fromstring(html) 
tds = root.cssselect("div#contents td.author") 

print tds   # gives [<Element td at 84ee2cc>] 
print tds[0].text # what you want, including the 'í'