Beautiful Soup i wyodrębnianie elementu div i jego zawartości przez identyfikator

147
soup.find("tagName", { "id" : "articlebody" })

Dlaczego to NIE zwraca <div id="articlebody"> ... </div>tagów i innych elementów? Nic nie zwraca. I wiem na pewno, że istnieje, ponieważ patrzę na to od razu

soup.prettify()

soup.find("div", { "id" : "articlebody" }) też nie działa.

( EDYCJA: Odkryłem, że BeautifulSoup nie analizował poprawnie mojej strony, co prawdopodobnie oznaczało, że strona, którą próbowałem przeanalizować, nie jest poprawnie sformatowana w SGML lub czymkolwiek)

Tony Stark
źródło
(Do twojej EDYCJI, to pytanie nadal ma wartość jako zasób wielokrotnego użytku dla innych, nawet jeśli parser nie działa na twojej konkretnej stronie)
smci

Odpowiedzi:

202

Powinieneś zamieścić swój przykładowy dokument, ponieważ kod działa dobrze:

>>> import BeautifulSoup
>>> soup = BeautifulSoup.BeautifulSoup('<html><body><div id="articlebody"> ... </div></body></html')
>>> soup.find("div", {"id": "articlebody"})
<div id="articlebody"> ... </div>

Znajdowanie <div>s w środku <div>działa również:

>>> soup = BeautifulSoup.BeautifulSoup('<html><body><div><div id="articlebody"> ... </div></div></body></html')
>>> soup.find("div", {"id": "articlebody"})
<div id="articlebody"> ... </div>
Lukáš Lalinský
źródło
2
mój przykładowy dokument jest ogromny. szukam problemu - myślę, że to nie działa w przypadku elementów div lub div. Policzyłem, ile elementów div znajduje się w dokumencie z print len ​​(zupa („div”)), co dało 10 i WYRAŹNIE widzę ponad 10 elementów div z firebug. więc myślę, że po prostu nie może znaleźć elementów div w elementach div, więc muszę zawęzić zawartość opakowania według opakowania.
Tony Stark
8
Cóż, nie można odpowiedzieć na twoje pytanie, kryształowe kule nie są niezawodnym sposobem debugowania. :)
Lukáš Lalinský
1
Wypróbowałem ten kod. div ma <embed> i nie mogę wydrukować w nim osadzonego.
Vincent,
13
lub prościejdiv = soup.find(id="articlebody")
jfs
4
lubsoup.find('div', id='articlebody')
Trevor Boyd Smith
71

Aby znaleźć element według jego id:

div = soup.find(id="articlebody")
jfs
źródło
15

Piękne Soup 4 obsługuje większość selektorów CSS z .select()metodą , dlatego można użyć idprzełącznika , takie jak:

soup.select('#articlebody')

Jeśli chcesz określić typ elementu, możesz dodać selektor typu przed idselektorem:

soup.select('div#articlebody')

.select()Sposób powraca zbiór elementów, co oznacza, że będzie takie same wyniki, jak w następującej .find_all()metody np

soup.find_all('div', id="articlebody")
# or
soup.find_all(id="articlebody")

Jeśli chcesz wybrać tylko jeden element, możesz po prostu użyć .find()metody :

soup.find('div', id="articlebody")
# or
soup.find(id="articlebody")
Josh Crozier
źródło
13

Myślę, że występuje problem, gdy znaczniki „div” są zbyt zagnieżdżone. Próbuję przeanalizować niektóre kontakty z pliku html Facebooka, a Beautifulsoup nie jest w stanie znaleźć tagów „div” z klasą „fcontent”.

Dzieje się tak również w przypadku innych klas. Kiedy ogólnie wyszukuję elementy div, zwraca tylko te, które nie są zagnieżdżone.

Kod źródłowy html może być dowolną stroną z Facebooka listy znajomych twojego znajomego (nie jednego z twoich znajomych). Jeśli ktoś może to przetestować i udzielić porady, byłbym bardzo wdzięczny.

To jest mój kod, w którym po prostu spróbuję wydrukować liczbę tagów „div” z klasą „fcontent”:

from BeautifulSoup import BeautifulSoup 
f = open('/Users/myUserName/Desktop/contacts.html')
soup = BeautifulSoup(f) 
list = soup.findAll('div', attrs={'class':'fcontent'})
print len(list)
omar
źródło
9

Najprawdopodobniej z powodu domyślnego parsera beautifulsoup ma problem. Zmień inny parser, na przykład „lxml” i spróbuj ponownie.

liang
źródło
To zadziałało dla mnie, dzięki! Użyłemsoup = BeautifulSoup(data, parser="html.parser")
will-hart
8

W źródle beautifulsoup ta linia pozwala na zagnieżdżanie elementów div w elementach div; więc twoja troska w komentarzu Lukasa nie byłaby uzasadniona.

NESTABLE_BLOCK_TAGS = ['blockquote', 'div', 'fieldset', 'ins', 'del']

Myślę, że musisz określić atrybuty, które chcesz, takie jak

source.find('div', attrs={'id':'articlebody'})
dagoof
źródło
5

próbowałeś soup.findAll("div", {"id": "articlebody"})?

brzmi szalenie, ale jeśli usuwasz rzeczy z natury, nie możesz wykluczyć wielu elementów div ...

user106514
źródło
4

Użyłem:

soup.findAll('tag', attrs={'attrname':"attrvalue"})

Jako moja składnia dla find / findall; To powiedziawszy, o ile nie ma innych opcjonalnych parametrów między tagiem a listą atrybutów, nie powinno to być inne.


źródło
4

Zdarzyło mi się również, gdy próbowałem zeskrobać Google.
Skończyło się na użyciu pyquery.
Zainstalować:

pip install pyquery

Posługiwać się:

from pyquery import PyQuery    
pq = PyQuery('<html><body><div id="articlebody"> ... </div></body></html')
tag = pq('div#articlebody')
Shoham
źródło
3

Oto fragment kodu

soup = BeautifulSoup(:"index.html")
titleList = soup.findAll('title')
divList = soup.findAll('div', attrs={ "class" : "article story"})

Jak widać, znajduję wszystkie tagi, a następnie znajduję wszystkie tagi z atrybutem class = "article" w środku

Rekursja
źródło
0

IdNieruchomość jest zawsze identyfikowany. Oznacza to, że możesz go używać bezpośrednio, nawet bez określania elementu. Dlatego jest to plus, jeśli twoje elementy mają to do przeanalizowania zawartości.

divEle = soup.find(id = "articlebody")
Iqra.
źródło