Problemas com a Parsing de BeautifulSoup
-
03-07-2019 - |
Pergunta
Estou tentando analisar uma página HTML com o BeautifulSoup, mas parece que o BeautifulSoup não gosta do HTML ou daquela página. Quando eu executo o código abaixo, o método prettify () me retorna apenas o bloco de script da página (veja abaixo). Alguém tem uma ideia por que isso acontece?
import urllib2
from BeautifulSoup import BeautifulSoup
url = "http://www.futureshop.ca/catalog/subclass.asp?catid=10607&mfr=&logon=&langid=FR&sort=0&page=1"
html = "".join(urllib2.urlopen(url).readlines())
print "-- HTML ------------------------------------------"
print html
print "-- BeautifulSoup ---------------------------------"
print BeautifulSoup(html).prettify()
A saída é produzida por BeautifulSoup.
-- BeautifulSoup ---------------------------------
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script language="JavaScript">
<!--
function highlight(img) {
document[img].src = "/marketing/sony/images/en/" + img + "_on.gif";
}
function unhighlight(img) {
document[img].src = "/marketing/sony/images/en/" + img + "_off.gif";
}
//-->
</script>
Obrigado!
ATUALIZAÇÃO: Estou usando a versão a seguir, que parece ser a mais recente.
__author__ = "Leonard Richardson (leonardr@segfault.org)"
__version__ = "3.1.0.1"
__copyright__ = "Copyright (c) 2004-2009 Leonard Richardson"
__license__ = "New-style BSD"
Solução
Tente com a versão 3.0.7a como Łukasz sugerido. O BeautifulSoup 3.1 foi projetado para ser compatível com o Python 3.0, então eles tiveram que mudar o analisador do SGMLPARSER para HTMLPARSER, que parece mais vulnerável ao HTML ruim.
De Changelog para o BeautifulSoup 3.1:
"A bela sopa agora é baseada em htmlparser, em vez de sgmlparser, que se foi no python 3. Há algum html ruim que o SGMLPARSER manuseou, mas o htmlparser não"
Outras dicas
Tentar lxml. Apesar do nome, é também para analisar e raspar o HTML. É muito, muito mais rápido que o BeautifulSoup, e até lida com o HTML "quebrado" melhor do que o BeautifulSoup, para que possa funcionar melhor para você. Ele também possui uma API de compatibilidade para o BeautifulSoup, se você não quiser aprender a API LXML.
Não há mais razão para usar o BeautifulSoup, a menos que você esteja no Google App Engine ou algo em que algo não puramente não é permitido.
BeautifulSoup não é mágico: se o HTML de entrada é horrível demais, não vai funcionar.
Nesse caso, o HTML recebido é exatamente isso: muito quebrado para o BeautifulSoup descobrir o que fazer. Por exemplo, ele contém marcação como:
Script Type = "" JavaScript ""
(Observe a citação dupla.)
Os documentos do BeautifulSoup contém uma seção o que você pode fazer se o belo GreatSoup não puder analisar sua marcação. Você precisará investigar essas alternativas.
Samj: Se eu conseguir coisas comoHTMLParser.HTMLParseError: bad end tag: u"</scr' + 'ipt>"
Acabei de remover o culpado da marcação antes de servi -lo para o BeautifulSoup e tudo é Dandy:
html = urllib2.urlopen(url).read()
html = html.replace("</scr' + 'ipt>","")
soup = BeautifulSoup(html)
Eu tive problemas para analisar o seguinte código também:
<script>
function show_ads() {
document.write("<div><sc"+"ript type='text/javascript'src='http://pagead2.googlesyndication.com/pagead/show_ads.js'></scr"+"ipt></div>");
}
</script>
Htmlparseerror: tag de final ruim: u '', na linha 26, coluna 127
Sam
Eu testei este script na versão do BeautifulSoup '3.0.7a' e ele retorna o que parece ser a saída correta. Não sei o que mudou entre '3.0.7a' e '3.1.0.1', mas experimente.
import urllib
from BeautifulSoup import BeautifulSoup
>>> page = urllib.urlopen('http://www.futureshop.ca/catalog/subclass.asp?catid=10607&mfr=&logon=&langid=FR&sort=0&page=1')
>>> soup = BeautifulSoup(page)
>>> soup.prettify()
No meu caso, executando as instruções acima, ele retorna toda a página HTML.