Sopa bonita e extração de uma div e seu conteúdo por ID

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

Por que isso NÃO retorna as <div id="articlebody"> ... </div>tags e outras coisas no meio? Não retorna nada. E eu sei de fato que existe, porque eu estou olhando direto para ele

soup.prettify()

soup.find("div", { "id" : "articlebody" }) também não funciona.

( EDIT: descobri que o BeautifulSoup não estava analisando corretamente minha página, o que provavelmente significa que a página que eu estava tentando analisar não está formatada corretamente em SGML ou o que for)

Tony Stark
fonte
(Para a sua edição, esta questão ainda tem valor como um recurso reutilizável para os outros, mesmo se o analisador não funciona na sua página particular)
SMCI

Respostas:

202

Você deve postar seu documento de exemplo, porque o código funciona bem:

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

Encontrar <div>s dentro de <div>s também funciona:

>>> soup = BeautifulSoup.BeautifulSoup('<html><body><div><div id="articlebody"> ... </div></div></body></html')
>>> soup.find("div", {"id": "articlebody"})
<div id="articlebody"> ... </div>
Lukáš Lalinský
fonte
2
meu exemplo de documento é enorme. Estou rastreando o problema - acho que isso não funciona em divs of divs. Fiz uma contagem de quantas divs existem no documento com print len ​​(sopa ('div')), que resultou em 10, e posso CLARAMENTE ver mais de 10 divs com o firebug. então eu acho que ele simplesmente não consegue encontrar divs dentro de divs, então preciso restringir as coisas wrapper por wrapper.
Tony Stark
8
Bem, é impossível responder à sua pergunta, as bolas de cristal não são uma maneira confiável de depurar. :)
Lukáš Lalinský
1
Eu tentei esse código. a div <embed> e eu não consigo imprimir a incorporação dentro dela.
Vincent
13
ou mais simplesmentediv = soup.find(id="articlebody")
jfs 05/05
4
ousoup.find('div', id='articlebody')
Trevor Boyd Smith
71

Para encontrar um elemento por id:

div = soup.find(id="articlebody")
jfs
fonte
15

O Beautiful Soup 4 suporta a maioria dos seletores de CSS com o .select()método , portanto, você pode usar um idseletor como:

soup.select('#articlebody')

Se você precisar especificar o tipo do elemento, poderá adicionar um seletor de tipo antes do idseletor:

soup.select('div#articlebody')

O .select()método retornará uma coleção de elementos, o que significa que retornaria os mesmos resultados do exemplo de .find_all()método a seguir:

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

Se você deseja selecionar apenas um único elemento, basta usar o .find()método :

soup.find('div', id="articlebody")
# or
soup.find(id="articlebody")
Josh Crozier
fonte
13

Acho que há um problema quando as tags 'div' estão muito aninhadas. Estou tentando analisar alguns contatos de um arquivo html do facebook e o Beautifulsoup não consegue encontrar as tags "div" com a classe "fcontent".

Isso acontece com outras classes também. Quando procuro divs em geral, ele gira apenas aqueles que não são muito aninhados.

O código-fonte html pode ser qualquer página do facebook da lista de amigos de um amigo seu (não o de seus amigos). Se alguém puder testá-lo e dar alguns conselhos, eu realmente aprecio isso.

Este é o meu código, onde apenas tento imprimir o número de tags "div" com a classe "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
fonte
9

Provavelmente, devido ao analisador de beautifulsoup padrão, há um problema. Altere um analisador diferente, como 'lxml' e tente novamente.

liang
fonte
Isso funcionou para mim, obrigado! Eu useisoup = BeautifulSoup(data, parser="html.parser")
will-hart
8

Na fonte beautifulsoup, essa linha permite que os divs sejam aninhados dentro de divs; portanto, sua preocupação com o comentário de lukas não seria válida.

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

O que eu acho que você precisa fazer é especificar os atributos que você deseja, como

source.find('div', attrs={'id':'articlebody'})
dagoof
fonte
5

você já tentou soup.findAll("div", {"id": "articlebody"})?

parece loucura, mas se você está pegando coisas do nada, não pode excluir vários divs ...

user106514
fonte
4

Eu usei:

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

Como minha sintaxe para encontrar / encontrar tudo; Dito isto, a menos que haja outros parâmetros opcionais entre a tag e a lista de atributos, isso não deve ser diferente.


fonte
4

Aconteceu comigo também ao tentar raspar o Google.
Acabei usando pyquery.
Instalar:

pip install pyquery

Usar:

from pyquery import PyQuery    
pq = PyQuery('<html><body><div id="articlebody"> ... </div></body></html')
tag = pq('div#articlebody')
Shoham
fonte
3

Aqui está um fragmento de código

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

Como você pode ver, encontro todas as tags e, em seguida, todas as tags com class = "article" dentro

Recursão
fonte
0

A Idpropriedade é sempre identificada exclusivamente. Isso significa que você pode usá-lo diretamente, sem especificar o elemento. Portanto, é um ponto positivo se os seus elementos tiverem que analisar o conteúdo.

divEle = soup.find(id = "articlebody")
Iqra.
fonte