如何从BeautifulSoup中提取CData
我有一个网站,想从中提取一些信息,网站的结构大致如下。我想从CData块中获取信息。
我正在使用BeautifulSoup来提取页面上的其他信息,所以如果解决方案能和这个工具一起使用,那就太好了,因为我还是个Python新手。具体来说,我想提取CData语句中隐藏的两种不同类型的数据。第一种数据只是文本,我觉得可以用正则表达式来处理,应该能得到我想要的。对于第二种类型的数据,如果能把包含HTML元素的数据单独放到一个BeautifulSoup对象里,我就可以解析它了。
我刚开始学习Python和BeautifulSoup,所以我在寻找那种神奇的方式,能够让我单独提取出CData。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>
Cows and Sheep
</title>
</head>
<body>
<div id="main">
<div id="main-precontents">
<div id="main-contents" class="main-contents">
<script type="text/javascript">
//<![CDATA[var _ = g_cow;_[7654]={cowname_enus:'cows rule!',leather_quality:99,icon:'cow_level_23'};_[37357]={sheepname_enus:'baa breath',wool_quality:75,icon:'sheep_level_23'};_[39654].cowmeat_enus = '<table><tr><td><b class="q4">cows rule!</b><br></br>
<!--ts-->
get it now<table width="100%"><tr><td>NOW</td><th>NOW</th></tr></table><span>244 Cows</span><br></br>67 leather<br></br>68 Brains
<!--yy-->
<span class="q0">Cow Bonus: +9 Cow Power</span><br></br>Sheep Power 60 / 60<br></br>Sheep 88<br></br>Cow Level 555</td></tr></table>
<!--?5695:5:40:45-->
';
//]]>
</script>
</div>
</div>
</div>
</body>
</html>
5 个回答
4
你可以试试这个:
from BeautifulSoup import BeautifulSoup
// source.html contains your html above
f = open('source.html')
soup = BeautifulSoup(''.join(f.readlines()))
s = soup.findAll('script')
cdata = s[0].contents[0]
这样应该能让你获取到cdata的内容。
更新
这个可能看起来更简洁一些:
from BeautifulSoup import BeautifulSoup
import re
// source.html contains your html above
f = open('source.html')
soup = BeautifulSoup(''.join(f.readlines()))
cdata = soup.find(text=re.compile("CDATA"))
这只是个人喜好,我觉得下面那个稍微好一点。
15
BeautifulSoup把CData看作是一种特殊的“可导航字符串”。举个例子:
import BeautifulSoup
txt = '''<foobar>We have
<![CDATA[some data here]]>
and more.
</foobar>'''
soup = BeautifulSoup.BeautifulSoup(txt)
for cd in soup.findAll(text=True):
if isinstance(cd, BeautifulSoup.CData):
print 'CData contents: %r' % cd
在你的情况下,你可以从ID为'main-contents'的div开始,查看它下面的内容,而不是在整个文档树中到处找。
17
在使用 BeautifulSoup 抓取 CData 时,有一点需要注意,就是不要使用 lxml 解析器。
默认情况下,lxml 解析器会把 CDATA 部分从文档中去掉,并用它的普通文本内容替代。想了解更多,可以点击 这里。
#Trying it with html.parser
>>> from bs4 import BeautifulSoup
>>> import bs4
>>> s='''<?xml version="1.0" ?>
<foo>
<bar><![CDATA[
aaaaaaaaaaaaa
]]></bar>
</foo>'''
>>> soup = BeautifulSoup(s, "html.parser")
>>> soup.find(text=lambda tag: isinstance(tag, bs4.CData)).string.strip()
'aaaaaaaaaaaaa'
>>>