2009-09-08 17 views
7

Próbuję zrobić skrobaczkę internetową, która będzie parsować stronę internetową publikacji i wypakować autorów. Szkieletowa struktura strony internetowej jest następujący:Skrobanie w Internecie Pythona z użyciem znaczników HTML z atrybutami

<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> 

Próbowałem użyć BeautifulSoup i lxml dotąd do wykonania tego zadania, ale nie jestem pewien, jak obsługiwać dwa znaczniki div i tag td, ponieważ mają atrybuty. Poza tym nie jestem pewien, czy powinienem polegać bardziej na BeautifulSoup lub lxml, czy na kombinacji obu. Co powinienem zrobić?

Obecnie mój kod wygląda to, co jest poniżej:

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) 

Zdaję sobie sprawę, że wiele sprawozdań na przywóz mogą być zbędne, ale po prostu skopiowane cokolwiek obecnie miał bardziej pliku źródłowego.

EDYCJA: Przypuszczam, że nie wyjaśniłem tego wyraźnie, ale mam wiele tagów na stronie, które chcę skrobać.

Odpowiedz

11

To nie jest dla mnie jasne, z pytaniem, dlaczego trzeba się martwić o div tagów - co robi tylko:

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

Na HTML dajesz, uruchomiony ten emituje dokładnie:

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

który wydaje się być tym, co chcesz. Być może możesz określić dokładnie to, czego potrzebujesz, a ten super prosty fragment się nie zgadza - wiele znaczników td oznacza wszystkie klasy td, z których musisz się zastanowić (wszystkie? Tylko niektóre? Które z nich?), Być może brakujące taki tag (co chcesz zrobić w tym przypadku) i tym podobne. Trudno wywnioskować, jakie dokładnie są twoje specyfikacje, właśnie z tego prostego przykładu i nadmiarowego kodu ;-).

Edit: jeśli, zgodnie z najnowszym komentarzu PO, istnieją liczne takie znaczniki td, jeden za autora:

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

... to znaczy, nie jest dużo trudniejszy w ogóle -)

+0

Dzięki, Alex. Mam wielu autorów na stronie, więc będę mieć wiele tagów td. Jak iterować po każdym z nich? – GobiasKoffi

1

BeautifulSoup to z pewnością kanoniczny parser/procesor HTML. Ale jeśli masz właśnie ten rodzaj fragmentu, który musisz dopasować, zamiast budować cały hierarchiczny obiekt reprezentujący HTML, pyparsing ułatwia zdefiniowanie początkowych i końcowych znaczników HTML w ramach tworzenia większego wyrażenia wyszukiwania:

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 

Funkcja makeHTMLTags w programie Pyparsing robi o wiele więcej niż tylko wyemitowanie wyrażeń "<tag>" i "</tag>".Zajmuje się również: dopasowanie

  • bezłuskową tagów
  • "<tag/>" składniowych
  • zero lub więcej atrybutów w znaczniku otwierającym
  • atrybuty zdefiniowane w dowolnej kolejności
  • nazwy atrybutów z przestrzeni nazw
  • wartości atrybutów w pojedynczej, podwójnej lub bez cudzysłowu
  • interweniująca biała spacja między znacznikiem i symbolami lub nazwą atrybutu, "=", Wartość d
  • atrybuty są dostępne po parsowania jako nazwane wyników

Są to typowe pułapki, gdy rozważa wykorzystanie regex do zgarniania HTML.

6

lub można używać pyquery, ponieważ BeautifulSoup nie jest aktywnie utrzymuje już, patrz http://www.crummy.com/software/BeautifulSoup/3.1-problems.html

najpierw zainstalować pyquery z

easy_install pyquery 

następnie skrypt może być tak proste, jak

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

pyquery używa składni selektora css znanej z jQuery, która jest bardziej intuicyjna niż BeautifulSoup. Używa pod spodem lxml i jest znacznie szybszy niż BeautifulSoup. Ale BeautifulSoup jest czystym pythonem, a zatem działa na silniku aplikacji Google, a także

5

Biblioteka lxml jest teraz standardem do parsowania html w pythonie. Interfejs może początkowo wydawać się niezręczny, ale jest bardzo przydatny w tym, co robi.

Powinieneś pozwolić, aby biblioteka obsługiwała specjalizację xml, na przykład te, które zawierały znaki ucieczki i byty;

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 'í' 
Powiązane problemy