我现在正在使用美丽的汤来解析网页,我听说它很有名,很好,但看起来不太合适。
这就是我做的事情
import urllib2
from bs4 import BeautifulSoup
page = urllib2.urlopen("http://www.cnn.com/2012/10/14/us/skydiver-record-attempt/index.html?hpt=hp_t1")
soup = BeautifulSoup(page)
print soup.prettify()
我认为这很简单。我打开网页并将其传递给beautifulsoup。但这就是我得到的:
Warning (from warnings module):
File "C:\Python27\lib\site-packages\bs4\builder\_htmlparser.py", line 149
"Python's built-in HTMLParser cannot parse the given document. This is not a bug in Beautiful Soup. The best solution is to install an external parser (lxml or html5lib), and use Beautiful Soup with that parser. See http://www.crummy.com/software/BeautifulSoup/bs4/doc/#installing-a-parser for help."))
...
HTMLParseError: bad end tag: u'</"+"script>', at line 634, column 94
我认为CNN网站设计得很好,所以我不太清楚会发生什么。有没有人对此有所了解?
答案 0 :(得分:10)
来自the docs:
如果可以的话,我建议你安装并使用lxml来提高速度。如果你是 使用早于2.7.3的Python 2版本或Python版本 3。早于3.2.2,安装lxml或者必须安装 html5lib-Python的内置HTML解析器在旧版本中并不是很好 版本
如果在Python 2.7上安装更强大的解析器(例如lxml或html5lib),您的代码将按原样(在Python 2.7,Python 3.3上)工作:
try:
from urllib2 import urlopen
except ImportError:
from urllib.request import urlopen # py3k
from bs4 import BeautifulSoup # $ pip install beautifulsoup4
url = "http://www.cnn.com/2012/10/14/us/skydiver-record-attempt/index.html?hpt=hp_t1"
soup = BeautifulSoup(urlopen(url))
print(soup.prettify())
答案 1 :(得分:8)
您不能使用BeautifulSoup或任何HTML解析器来阅读网页。您永远不能保证网页是一个格式良好的文档。让我解释一下这个案例中发生的事情。
在该页面上有这个INLINE javascript:
var str="<script src='http://widgets.outbrain.com/outbrainWidget.js'; type='text/javascript'></"+"script>";
您可以看到它正在创建一个将脚本标记放到页面上的字符串。现在,如果你是一个HTML解析器,这是一个非常棘手的事情。当你突然点击<script>
标签时,你会继续读取你的标记。现在,不幸的是,如果你这样做了:
<script>
alert('hello');
<script>
alert('goodby');
大多数解析器会说:好的,我找到了一个开放的脚本标记。哦,我找到了另一个开放的脚本标签!他们一定忘了关闭第一个!并且解析器会认为两者都是有效的脚本。
因此,在这种情况下,BeautifulSoup会看到<script>
标记,而即使它在javascript字符串中,看起来它可能是一个有效的起始标记,而BeautifulSoup有一个癫痫发作,以及它应该。
如果你再看一下这个字符串,你可以看到他们做了这件有趣的工作:
... "</" + "script>";
这看起来很奇怪吗?如果不进行额外的字符串连接就行str = " ... </script>"
不是更好吗?这实际上是一个常见的技巧(愚蠢的人将脚本标记写成字符串,这是一种不好的做法),使解析器不会中断。因为如果你这样做:
var a = '</script>';
在内联脚本中,解析器会出现并且真正看到</script>
并认为整个脚本标记已经结束,并将该脚本标记的其余内容作为纯文本抛出到页面上。这是因为即使您的JS语法无效,您也可以在技术上将关闭脚本标记放在任何位置。从解析器的角度来看,最好尽早退出脚本标记,而不是尝试将html代码渲染为javascript。
因此,您无法使用常规HTML解析器来解析网页。这是一场非常非常危险的比赛。无法保证您将获得格式良好的HTML。根据您要执行的操作,您可以使用正则表达式阅读页面内容,或尝试使用headless browser
获取完全呈现的页面内容答案 2 :(得分:2)
你需要使用带BeautifulSoup的html5lib解析器
要安装reqd解析器,请使用pip:
pip install html5lib
然后以这种方式使用该解析器
import mechanize
br = mechanize.Browser()
html = br.open("http://google.com/",timeout=100).read()
soup = BeautifulSoup(html,'html5lib')
a_s = soup.find_all('a')
for i in range(0,len(a_s)):
print a_s[i]['href']
答案 3 :(得分:1)
您可以做的最简单的事情之一是,将内容指定为“lxml”。您可以通过将“lxml”添加到urlopen()函数作为参数
来实现page = urllib2.urlopen(“[url]”,“lxml”)
然后你的代码如下。
import urllib2from bs4 import BeautifulSoup
page = urllib2.urlopen("http://www.cnn.com/2012/10/14/us/skydiver-record-attempt/index.html?hpt=hp_t1","lxml")
soup = BeautifulSoup(page)
print soup.prettify()
到目前为止,我没有遇到任何麻烦:)