我如何从BeautifulSoup中取出CData

har*_*lke 6 python screen-scraping 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>
Run Code Online (Sandbox Code Playgroud)

iMa*_*ath 13

您需要注意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'
>>> 
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 12

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
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您当然可以查看从div开始的子树,其中包含"main-contents"ID,而不是整个文档树.

  • 似乎这种方法仅适用于尚未注释掉的 CDATA 标记。在原始问题的示例中,找不到 CDATA。 (3认同)

RJ *_*old 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]
Run Code Online (Sandbox Code Playgroud)

这应该会给你 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"))
Run Code Online (Sandbox Code Playgroud)

只是个人喜好,但我更喜欢下面的那一个。