From 64753365df3bedd60cde505db792abb20841ada4 Mon Sep 17 00:00:00 2001
From: Leonard Richardson The Dormouse's story Once upon a time there were three little sisters; and their names were
- Elsie,
- Lacie and
- Tillie;
- and they lived at the bottom of a well. ...
- #
- # The Dormouse's story
- #
- #
- # Once upon a time there were three little sisters; and their names were
- #
- # Elsie
- #
- # ,
- #
- # Lacie
- #
- # and
- #
- # Tillie
- #
- # ; and they lived at the bottom of a well.
- #
- # ...
- # The Dormouse's story Back to the homepage Back to the homepage The Dormouse's story Once upon a time there were three little sisters; and their names were
- Elsie,
- Lacie and
- Tillie;
- and they lived at the bottom of a well. ... The Dormouse's story ", e daí por diante. O Beautiful Soup oferece ferramentas
-para reconstruir a análise inicial do documento.
-
-.. _element-generators:
-
-``.next_element`` e ``.previous_element``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-O atributo ``.next_element`` de uma string ou tag aponta para
-qualquer coisa que tenha sido interpretado posteriormente.
-Isso deveria ser o mesmo que ``.next_sibling``, mas é
-drasticamente diferente.
-
-Aqui está a tag final no "three sisters". Sua
-``.next_sibling`` é uma string: a conclusão da sentença
-que foi interrompida pelo início da tag .::
-
- last_a_tag = soup.find("a", id="link3")
- last_a_tag
- # Tillie
-
- last_a_tag.next_sibling
- # '; and they lived at the bottom of a well.'
-
-Mas no ``.next_element`` da tag , o que é analisado imediatamente
-depois da tag `não` é o resto da sentença: é a palavra "Tillie".
-
- last_a_tag.next_element
- # u'Tillie'
-
-Isso porque na marcação original, a palavra "Tillie" apareceu
-antes do ponto e virgula. O parser encontrou uma tag , então
-a palavra "Tillie", então fechando a tag , então o ponto e vírgula e o
-resto da sentença. O ponto e vírgula estão no mesmo nível que a tag ,
-mas a palavra "Tillie" foi encontrada primeiro.
-
-O atributo ``.previous_element`` é exatamente o oposto de
-``.next_element``. Ele aponta para qualquer elemento que
-seja analisado antes do respectivo::
-
- last_a_tag.previous_element
- # u' and\n'
- last_a_tag.previous_element.next_element
- # Tillie
-
-``.next_elements`` e ``.previous_elements``
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-Você deve ter entendido a idéia agora. Você pode usar estes iteradores
-para andar para frente e para atrás no documento quando ele for analisado::
-
- for element in last_a_tag.next_elements:
- print(repr(element))
- # u'Tillie'
- # u';\nand they lived at the bottom of a well.'
- # u'\n\n'
- # ... The Dormouse's story Once upon a time there were three little sisters; and their names were
- Elsie,
- Lacie and
- Tillie;
- and they lived at the bottom of a well. ... ::
-
- soup.find_all(has_class_but_no_id)
- # [ The Dormouse's story Once upon a time there were... ... . Não irá encontrar as tags ,
-porque elas definem "class e "id" ao mesmo tempo. Ela não encontrará
-as tags e The Dormouse's story com a classe CSS "title"?
-Vamos dar uma olhada nos argumentos de ``find_all()``.
-
-.. _name:
-
-O argumento ``name``
-^^^^^^^^^^^^^^^^^^^^
-
-Passe um valor para ``name`` e você dirá para o Beautiful Soup
-considerar apenas as tags com certos nomes. Strings de texto seão ignoradas,
-assim como os nomes que não corresponderem ao argumento ``name``
-
-Este é o uso mais simples::
-
- soup.find_all("title")
- # [ The Dormouse's story Once upon a time there were three little sisters; and their names were
- # Elsie,
- # Lacie and
- # Tillie;
- # and they lived at the bottom of a well. é uma mãe
-indireta da string e nossa busca também a encontra. Há uma tag com
-a classe CSS "title" em algum lugar no documento, mas não é nenhuma das tags mães
-da string, portanto, não podemos encontrá-la com ``find_parents()``.
-
-Você já deve ter feito a conexão entre ``find_parent()`` e
-``find_parents()``, e os atributos `.parent`_ e `.parents`_ mencionados
-anteriormente. A conexão é muito forte. Estes métodos de busca utilizam ``.parents``
-para iterar sobre todos as mãesS e compara cada um com o filtro passado
-para verificar se preenche o requisito.
-
-``find_next_siblings()`` e ``find_next_sibling()``
-----------------------------------------------------
-
-Signature: find_next_siblings(:ref:`name ... The Dormouse's story ... do documento foi
-encontrada, mesmo que não esteja na mesma parte da árvore que onde começamos.
-Para estes métodos, o que importa é que um elemento corresponda ao filtro e esteja
-depois do elemento de início no documento.
-
-``find_all_previous()`` e ``find_previous()``
------------------------------------------------
-
-Signature: find_all_previous(:ref:`name Once upon a time there were three little sisters; ... The Dormouse's story que contém a tag por onde começamos.
-Isso não deveria ser tão surpreendente: nós estamos olhando para todas as tags
-que apareceram anteriormente no documento incluindo aquela onde começamos. Uma
-tag que contenha uma tag deve aparecer antes da tag que ela contém.
-
-Seletores CSS
--------------
-
-A partir da versão 4.7.0, o Beautiful Soup suporta a maior parte dos seletores CSS4
-através do projeto `SoupSieve ... I wish I was bold. I wish I was bold. A one A one, a two
- # A one
- # , a two
- #
- # A one, a two
- # The law firm of Dewey, Cheatem, & Howe The law firm of Dewey, Cheatem, & Howe Il a dit <<Sacré bleu!>>
- # Il a dit <<Sacré bleu!>>
- #
- # Il a dit <<Sacré bleu!>>
- #
- # Il a dit <
- # IL A DIT <Extremely bold
-
-Atributos
-^^^^^^^^^^
-Uma tag pode ter inúmeros atributos. A tag ````
-possui um atributo "id" que possui o valor "boldest". Você pode
-acessar um atributo de uma tag tratando-a como um dicionário::
-
- tag['id']
- # u'boldest'
-
-Você pode acessar este dicionário diretamente através de ``.attrs``::
-
- tag.attrs
- # {u'id': 'boldest'}
-
-Você pode adicionar, remover ou modificar os atributos de uma tag. Novamente, isso pode
-ser feito tratando a tag como um dicionário::
-
- tag['id'] = 'verybold'
- tag['another-attribute'] = 1
- tag
- #
-
- del tag['id']
- del tag['another-attribute']
- tag
- #
-
- tag['id']
- # KeyError: 'id'
- print(tag.get('id'))
- # None
-
-.. _multivalue:
-
-Atributos com múltiplos valores
-&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
-
-O HTML 4 define alguns atributos que podem ter múltiplos valores. O HTML 5
-removeu alguns deles, mas definiu alguns novos. O atributo mais comum
-que pode receber múltiplos valores é o ``class`` (ou seja, a tag pode ter mais de uma classe CSS).
-Outros são ``rel``, ``rev``, ``accept-charset``, ``headers``, e ``accesskey``.
-O Beautiful Soup apresenta o(s) valor(es) de um atributo deste tipo como uma lista::
-
- css_soup = BeautifulSoup('')
- css_soup.p['class']
- # ["body"]
-
- css_soup = BeautifulSoup('')
- css_soup.p['class']
- # ["body", "strikeout"]
-
-Se um atributo possui mais de um valor, mas não é um atributo
-que aceita múltiplos valores conforme definido por qualquer versão do
-padrão HTML, o Beautiful Soup retornará como um valor único::
-
- id_soup = BeautifulSoup('')
- id_soup.p['id']
- # 'my id'
-
-Quando a tag é transformada novamente em string, os valores do atributo múltiplo
-são consolidados::
-
- rel_soup = BeautifulSoup('No longer bold
-
-``NavigableString`` suporta a maior parte das características descritas em
-`Navegando pela árvore`_ e `Buscando na árvore`_, mas não todas elas.
-Em particular, desde que uma string não pode conter de tudo (da maneira que
-uma tag pode conter uma string ou outra tag), as strings não suportam os
-atributos ``.contents`` ou ``.string`` ou o método ``find()``.
-
-Se você quer utilizar uma ``NavigableString`` fora do Beautiful Soup,
-você deve chamar o ``unicode()`` para transformá-la em uma string Unicode Python
-padrão. Se você não fizer isso, sua string irá carregar uma referência de toda sua
-árvore Beautiful Soup, mesmo que você já não esteja mais usando ela, o que é um grande
-desperdício de memória.
-
-``BeautifulSoup``
------------------
-
-O objeto ``BeautifulSoup`` em si representa o documento como um todo.
-Para maioria dos propósitos, você pode tratá-lo como um objeto :ref:`Tag`.
-Isso significa que irá suportar a maioria dos métodos descritos em
-`Navegando pela árvore`_ e `Buscando na árvore`_.
-
-Sabendo que o objeto ``BeautifulSoup`` não corresponde a uma tag
-HTML ou XML propriamente dita, ele não tem nome e nem atributos. Mas em alguns
-casos é útil observar seu ``.name``; então, foi dado o especial
-``.name`` "[document]"::
-
- soup.name
- # u'[document]'
-
-Comentários e outras strings especiais
---------------------------------------
-
-``Tag``, ``NavigableString``, e ``BeautifulSoup`` abrangem quase
-tudo o que você encontrará em um arquivo HTML ou XML, mas há alguns
-pontos faltando. O único deles que você provavelmente precisará se preocupar
-é o comentário::
-
- markup = ""
- soup = BeautifulSoup(markup)
- comment = soup.b.string
- type(comment)
- # Extremely bold
-
- del tag['class']
- del tag['id']
- tag
- # Extremely bold
-
-Modificando ``.string``
------------------------
-
-Se você definir o um atributo ``.string`` de uma tag, o conteúdo da
-tag será substituido pela string que foi passada::
-
- markup = 'I linked to example.com'
- soup = BeautifulSoup(markup)
-
- tag = soup.a
- tag.string = "New link text."
- tag
- # New link text.
-
-Cuidado: se a tag conter outra(s) tag(s), ela(s) e todo seu conteúdo
-serão destruídos.
-
-``append()``
-------------
-
-Você pode adicionar algo no conteúdo de uma tag com ``Tag.append()``. Funciona
-da mesma maneira que ``.append()`` de uma lista::
-
- soup = BeautifulSoup("Foo")
- soup.a.append("Bar")
-
- soup
- # FooBar
- soup.a.contents
- # [u'Foo', u'Bar']
-
-``extend()``
-------------
-
-Com início no Beautiful Soup 4.7.0, ``Tag`` também suporta um método chamado
-``.extend()``, o qual funciona da mesma maneira que chamando ``.extend()`` em
-uma lista::
-
- soup = BeautifulSoup("Soup")
- soup.a.extend(["'s", " ", "on"])
-
- soup
- # Soup's on
- soup.a.contents
- # [u'Soup', u''s', u' ', u'on']
-
-``NavigableString()`` e ``.new_tag()``
--------------------------------------------------
-
-Se você precisar adicionar uma string a um documento, sem problema -- você
-pode passar uma string Python através de ``append()``, ou você pode chamar
-o construtor ``NavigableString``::
-
- soup = BeautifulSoup("")
- tag = soup.b
- tag.append("Hello")
- new_string = NavigableString(" there")
- tag.append(new_string)
- tag
- # Hello there.
- tag.contents
- # [u'Hello', u' there']
-
-Se você quiser criar um comentário ou alguma outra subclasse de
-``NavigableString``, apenas chame o construtor::
-
- from bs4 import Comment
- new_comment = Comment("Nice to see you.")
- tag.append(new_comment)
- tag
- # Hello there
- tag.contents
- # [u'Hello', u' there', u'Nice to see you.']
-
-(Esta é uma funcionalidade nova no Beautiful Soup 4.4.0.)
-
-E se você precisar criar uma nova tag? A melhor solução
-é chamar o método ``BeautifulSoup.new_tag()``::
-
- soup = BeautifulSoup("")
- original_tag = soup.b
-
- new_tag = soup.new_tag("a", href="http://www.example.com")
- original_tag.append(new_tag)
- original_tag
- #
-
- new_tag.string = "Link text."
- original_tag
- # Link text.
-
-Somente o primeiro argumento (o nome da tag) é obrigatório.
-
-``insert()``
-------------
-
-``Tag.insert()`` funciona assim como ``Tag.append()``, exceto que o novo elemento
-não será inserido ao final do ``.contents`` de sua tag mãe. Ele será inserido em qualquer posição
-numérica que você informar. Funciona assim como ``.insert()`` em uma lista::
-
- markup = 'I linked to example.com'
- soup = BeautifulSoup(markup)
- tag = soup.a
-
- tag.insert(1, "but did not endorse ")
- tag
- # I linked to but did not endorse example.com
- tag.contents
- # [u'I linked to ', u'but did not endorse', example.com]
-
-``insert_before()`` e ``insert_after()``
-------------------------------------------
-
-O método ``insert_before()`` insere tags ou strings imediatamente antes de algo
-na árvore::
-
- soup = BeautifulSoup("stop")
- tag = soup.new_tag("i")
- tag.string = "Don't"
- soup.b.string.insert_before(tag)
- soup.b
- # Don'tstop
-
-O método ``insert_after()`` insere tags ou strings imediatamente após algo
-na árvore::
-
- div = soup.new_tag('div')
- div.string = 'ever'
- soup.b.i.insert_after(" you ", div)
- soup.b
- # Don't you
")
-
- print(soup.encode(formatter="html"))
- #
-
- print(soup.encode(formatter="html5"))
- #
-
-Se você passar ``formatter=None``, Beautiful Soup não irá modificar
-as strings na saída. Esta é a opção mais rápida, mas permitirá que o
-Beautiful Soup gere HTML/XML inválidos, como nestes exemplos::
-
- print(soup.prettify(formatter=None))
- #
- #
- #
aberta. Este parser também adiciona uma tag
vazia ao documento. - -Aqui está o mesmo documento analisado com o parser HTML nativo do Python:: - - BeautifulSoup("", "html.parser") - # - -Assim como html5lib, este parser ignora a tag de fechamento . -Este parser também não realiza nenhuma tentatida de criar um HTML bem -formatado adicionando uma tag . Como lxml, ele nem se importa em -adicionar uma tag . - -Sendo o documento "" inválido, nenhuma dessas técnicas é a maneira -"correta" de lidar com isso. O html5lib utiliza técnicas que são parte -do padrão HTML5, portanto vendo sendo definido como a maneira "mais correta", -mas todas as três técnicas são legítimas. - -Diferenças entre analisadores podem afetar o seu script. Se você está -planejando distribuir seu script para outras pessoas, ou rodá-lo em -múltiplas máquinas, você deve especificar o analisador no construtor -``BeautifulSoup``. Isso irá reduzir as chances de que seus usuários -analisem um documento de forma diferente da maneira como você analisou. - - -Codificação (Encoding) -====================== - -Todo documento HTML ou XML é escrito em uma codificação (encoding) específica como ASCII -ou UTF-8. Mas quando você carrega um documento no BeautifulSoup, você irá descobrir -que ele foi convertido para Unicode:: - - markup = "Sacr\xe9 bleu!
- - - ''' - - soup = BeautifulSoup(markup) - print(soup.prettify()) - # - # - # - # - # - #- # Sacré bleu! - #
- # - # - -Note que a tag foi reescrita para refletir o fato que o documento -é agora um UTF-8. - -Se você não quiser um UTF-8, você pode passar a codificação desejada como parâmetro de -``prettify()``:: - - print(soup.prettify("latin-1")) - # - # - # - # ... - -Você também pode chamar encode() no objeto ``BeautifulSoup`` ou em qualquer elemento -do objeto, assim como se faz em uma string Python:: - - soup.p.encode("latin-1") - # 'Sacr\xe9 bleu!
' - - soup.p.encode("utf-8") - # 'Sacr\xc3\xa9 bleu!
' - -Qualquer caractere que não pode ser representado na codificação escolhida -irá ser convertida para uma entidade de referência numérica XML. Abaixo você -tem um documento que inclui o caractere Unicode SNOWMAN:: - - markup = u"\N{SNOWMAN}" - snowman_soup = BeautifulSoup(markup) - tag = snowman_soup.b - -O caractere SNOWMAN faz parte da documentação UTF-8 (algo como -☃), mas não possui representação para este caractere em ISO-latin-1 ou -ASCII, portanto ele é convertido para "☃" para as essas codificações:: - - print(tag.encode("utf-8")) - # ☃ - - print tag.encode("latin-1") - # ☃ - - print tag.encode("ascii") - # ☃ - -Unicode, Dammit ---------------- - -Você pode usar o `Unicode, Dammit` fora do Beautiful Soup. É útil -quando você possui dados em uma codificação desconhecida e quer -simplesmente convertê-la para Unicode:: - - from bs4 import UnicodeDammit - dammit = UnicodeDammit("Sacr\xc3\xa9 bleu!") - print(dammit.unicode_markup) - # Sacré bleu! - dammit.original_encoding - # 'utf-8' - - -As respostas do `Unicode, Dammit` serão um pouco mais precisas se você -instalar as bibliotecas ``chardet`` ou ``cchardet``. Quanto maior a quantidade -de dados no arquivo que você passar para o `Unicode, Dammit`, mais precisas serão -as conversões. Se você possui suas suspeitas sobre qual a codificação original, -você pode passar as opções em uma lista:: - - dammit = UnicodeDammit("Sacr\xe9 bleu!", ["latin-1", "iso-8859-1"]) - print(dammit.unicode_markup) - # Sacré bleu! - dammit.original_encoding - # 'latin-1' - -`Unicode, Dammit` possui duas características que o Beautiful Soup não utiliza. - -Smart quotes -^^^^^^^^^^^^ - -Você pode utilizar `Unicode, Dammit` para converter Microsoft smart quotes para -entidades HTML ou XML:: - - markup = b"I just \x93love\x94 Microsoft Word\x92s smart quotes
" - - UnicodeDammit(markup, ["windows-1252"], smart_quotes_to="html").unicode_markup - # u'I just “love” Microsoft Word’s smart quotes
' - - UnicodeDammit(markup, ["windows-1252"], smart_quotes_to="xml").unicode_markup - # u'I just “love” Microsoft Word’s smart quotes
' - -Você também pode converter Microsoft smart quotes para ASCII:: - - UnicodeDammit(markup, ["windows-1252"], smart_quotes_to="ascii").unicode_markup - # u'I just "love" Microsoft Word\'s smart quotes
' - -Espero que você ache estas características úteis, mas o Beautiful Soup não -as usa.O Beautiful Soup dá preferência ao comportamento padrão, que é -converter para caracteres Unicode:: - - UnicodeDammit(markup, ["windows-1252"]).unicode_markup - # u'I just \u201clove\u201d Microsoft Word\u2019s smart quotes
' - -Codificação Inconsistente -^^^^^^^^^^^^^^^^^^^^^^^^^ - -Algumas vezes um documento é em sua maioria UTF-8, mas contém caracteres -Windows-1252 assim como (de novo) Microsoft smart quotes. Isso pode acontecer -quando um website compostos de dados de muitas fontes diferentes. Você pode -utilizar ``UnicodeDammit.detwingle()`` para transformar este documento em um -UTF-8 puro. Aqui está um exemplo:: - - snowmen = (u"\N{SNOWMAN}" * 3) - quote = (u"\N{LEFT DOUBLE QUOTATION MARK}I like snowmen!\N{RIGHT DOUBLE QUOTATION MARK}") - doc = snowmen.encode("utf8") + quote.encode("windows_1252") - -Este documento é uma bagunça. O snowmen é um UTF-8 e as aspas são Windows-1252. -Você pode exibir o snowmen ou as aspas, mas não os dois ao mesmo tempo:: - - print(doc) - # ☃☃☃�I like snowmen!� - - print(doc.decode("windows-1252")) - # ☃☃☃“I like snowmen!” - -Decodificar um documento como UTF-8 gera um ``UnicodeDecodeError``, e -como um Windows-1252 lhe tras algo sem sentido. Felizmente, -``UnicodeDammit.detwingle()`` irá converter a string para UTF-8 puro, -permitindo a você decodificá-la para Unicode e exibir o snowmen e as -aspas simultaneamente:: - - new_doc = UnicodeDammit.detwingle(doc) - print(new_doc.decode("utf8")) - # ☃☃☃“I like snowmen!” - -``UnicodeDammit.detwingle()`` sabe apenas como trabalhar com Windows-1252 -contido em UTF-8 (ou vice versa, eu suponho), mas este é o caso mais comum. - -Note que você deve chamar ``UnicodeDammit.detwingle()`` em seu dado -antes de passá-lo para ``BeautifulSoup`` ou para o construtor ``UnicodeDammit``. -O Beautiful Soup assume que um documento possui apenas uma codificação, -independente de qual ela seja. Se você passar um documento que -contém ambos UTF-8 e Windows-1252, é provável que ele pense que todo -o documento seja Windows-1252, e o documento parecerá ``☃☃☃“I like snowmen!”``. - -``UnicodeDammit.detwingle()`` é novo no Beautiful Soup 4.1.0. - -Linhas numeradas -================ - -Os interpretadores ``html.parser` e ``html5lib`` podem rastrear onde, no -documento original, cada tag foi encontrada. Você pode acessar esta -informação através de ``Tag.sourceline`` (número da linha) e ``Tag.sourcepos`` -(posição do início da tag na linha):: - - markup = "Paragraph 1
\nParagraph 2
" - soup = BeautifulSoup(markup, 'html.parser') - for tag in soup.find_all('p'): - print(tag.sourceline, tag.sourcepos, tag.string) - # (1, 0, u'Paragraph 1') - # (2, 3, u'Paragraph 2') - -Note que os dois interpretadores significam coisas levemente diferentes por -``sourceline`` e ``sourcepos``. Para html.parser, estes números representam -a posição do sinal `menor que`inicial. Para html5lib, representa a posição -do sinal `maior que` final:: - - soup = BeautifulSoup(markup, 'html5lib') - for tag in soup.find_all('p'): - print(tag.sourceline, tag.sourcepos, tag.string) - # (2, 1, u'Paragraph 1') - # (3, 7, u'Paragraph 2') - -Você pode desabilitar esta característica passando ``store_line_numbers=False` -no construtor ``BeautifulSoup``:: - - markup = "Paragraph 1
\nParagraph 2
" - soup = BeautifulSoup(markup, 'html.parser', store_line_numbers=False) - soup.p.sourceline - # None - -Esta característica é nova no 4.8.1 e os analisadores baseados no lxml -não a suportam. - -Comparando objetos por igualdade -============================== - -O Beautiful Soup diz que dois objetos ``NavigableString`` ou ``Tag`` são -iguais quando eles apresentam as mesma marcação HTML ou XML. No exemplo -abaixo, as duas tags são tratadas como iguais, mesmo estando em partes -diferentes da árvore do objeto, porque ambas estão como "pizza":: - - markup = "I want pizza and more pizza!
" - soup = BeautifulSoup(markup, 'html.parser') - first_b, second_b = soup.find_all('b') - print first_b == second_b - # True - - print first_b.previous_element == second_b.previous_element - # False - -Se você quiser verificar se duas variáveis se referem exatamente ao -mesmo objeto, use `is`:: - - print first_b is second_b - # False - -Copiando objetos Beautiful Soup -=============================== - -Você pode utilizar ``copy.copy()`` para criar uma cópia de qualquer ``Tag`` ou -``NavigableString``:: - - import copy - p_copy = copy.copy(soup.p) - print p_copy - #I want pizza and more pizza!
- - -A cópia será considerada igual ao original, desde que ela apresente a mesma -marcação que o original, mas não será o mesmo objeto:: - - print soup.p == p_copy - # True - - print soup.p is p_copy - # False - -A única diferença real é que a cópia é completamente separada da árvore -original do Beautiful Soup, como se ``extract()`` fosse chamado para ela:: - - print p_copy.parent - # None - -Isso acontece porque dois objetos ``Tag`` diferentes não podem ocupar o mesmo -espaço ao mesmo tempo. - - -Analisando apenas parte de um documento -======================================= - -Suponhamos que você queira que o Beautiful Soup olhe apenas para as -tags de um documento. É um desperdício de tempo e memória analisar -todo o documento e, posteriormente, analisar novamente apenas para buscar -as tags . Seria muito mais rápido ignorar tudo o que não for em -primeiro lugar. A classe ``SoupStrainer`` permite que você escolha -qual partes do documento serão analisadas. Você deverá penas criar uma -instância de ``SoupStrainer`` e passá-la ao construtor ``BeautifulSoup`` -no argumento ``parse_only``. - -(Note que *esta característica não funcionará se você estiver utilizando -o html5lib*. Se você utilizar o html5lib, todo o documento será analisado. -Isso acontece porque html5lib constantemente reorganiza a árvore de análise -e se alguma parte do documento realmente não fizer parte dela, ela irá quebrar. -Para evitar confusão, no exemplo abaixo, forçarei o Beautiful Soup a usar o -analisador nativo do Python). - -``SoupStrainer`` ----------------- - -A classe ``SoupStrainer`` recebe os mesmos argumentos que qualquer método em `Buscando na árvore`_: :ref:`nameThe Dormouse's story
- -Once upon a time there were three little sisters; and their names were - Elsie, - Lacie and - Tillie; - and they lived at the bottom of a well.
- -...
- """ - - print(BeautifulSoup(html_doc, "html.parser", parse_only=only_a_tags).prettify()) - # - # Elsie - # - # - # Lacie - # - # - # Tillie - # - - print(BeautifulSoup(html_doc, "html.parser", parse_only=only_tags_with_id_link2).prettify()) - # - # Lacie - # - - print(BeautifulSoup(html_doc, "html.parser", parse_only=only_short_strings).prettify()) - # Elsie - # , - # Lacie - # and - # Tillie - # ... - # - -Você pode também passar um ``SoupStrainer`` em qualquer método coberto em `Buscando na árvore`_. -Este uso provavelmente não seja muito útil, mas pensei que deveria mencioná-lo:: - - soup = BeautifulSoup(html_doc) - soup.find_all(only_short_strings) - # [u'\n\n', u'\n\n', u'Elsie', u',\n', u'Lacie', u' and\n', u'Tillie', - # u'\n\n', u'...', u'\n'] - -Solucionando Problemas -====================== - -.. _diagnose: - -``diagnose()`` --------------- - -Se você está tendo problemas em entender o que o Beautiful Soup está -fazendo com um documento, passe o documento pela função ``diagnose()``. (Nova no Beautiful Soup 4.2.0.) -O Beautiful Soup irá retornar um relatório mostrando como diferentes parsers -lidam com o documento e irá lhe dizer o Beautiful Soup poderia estar utilizando outro parser:: - - from bs4.diagnose import diagnose - with open("bad.html") as fp: - data = fp.read() - diagnose(data) - - # Diagnostic running on Beautiful Soup 4.2.0 - # Python version 2.7.3 (default, Aug 1 2012, 05:16:07) - # I noticed that html5lib is not installed. Installing it may help. - # Found lxml version 2.3.2.0 - # - # Trying to parse your data with html.parser - # Here's what html.parser did with the document: - # ... - -Olhando para o que diagnose() retorna, poderá lhe dizer como resolver -o seu problema. Mesmo que não consiga, você poderá colar a saída de ``diagnose()`` -quando solicitar ajuda. - -Erros enquanto se analisa um documento --------------------------------------- - -Existem dois tipos diferentes de erros de análise. Existem quebras -quando você passa para o Beautiful Soup um documento e ele retorna uma -exceção, geralmente um ``HTMLParser.HTMLParseError``. E existe o comportamento -inesperado, quando uma árvore de análise parece um pouco diferente do -documento usado para criá-la. - -Quase nenhum destes problemas são parte do Beautiful Soup. Não é -porque o Beautiful Soup é maravilhosamente um software bem escrito. É -porque o Beautiful Soup não inclui nenhum código de análise. Ao invés disso, -ele depende de analisadores externos. Se um analisador não funciona com -certo documento, a melhor solução é tentar um analisador diferente. Veja -`Instalando um analisador`_ para detalhes e uma comparação entre eles. - -Os erros de interpretação mais comuns são ``HTMLParser.HTMLParseError: - -malformed start tag`` e ``HTMLParser.HTMLParseError: bad end -tag``. Existem dois parsers gerados para o parser built in do Python -e a solução é :ref:`install lxml ou html5lib.