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)


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

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


4
ousoup.find('div', id='articlebody')
Trevor Boyd Smith

71

Para encontrar um elemento por id:

div = soup.find(id="articlebody")

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

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)

9

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


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'})

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


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.


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

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


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")
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.