我正在使用Beautiful Soup从网页中提取“内容”。我知道有些人以前问过这个问题,他们都被指向美丽的汤,这就是我开始使用它的方式。
我能够成功获取大部分内容,但我在使用作为内容一部分的标签时遇到了一些挑战。(我从一个基本策略开始:如果一个节点中有多个 x-chars,那么它就是内容)。我们以下面的html代码为例:
<div id="abc">
some long text goes <a href="/"> here </a> and hopefully it
will get picked up by the parser as content
</div>
results = soup.findAll(text=lambda(x): len(x) > 20)
当我使用上面的代码获取长文本时,它会在标签处中断(识别的文本将从“并且希望..”开始)。所以我尝试用纯文本替换标签,如下所示:
anchors = soup.findAll('a')
for a in anchors:
a.replaceWith('plain text')
以上不起作用,因为 Beautiful Soup 将字符串作为 NavigableString 插入,当我使用 len(x) > 20 的 findAll 时会导致同样的问题。我可以使用正则表达式首先将 html 解析为纯文本,清除所有不需要的标签,然后调用 Beautiful Soup。但我想避免两次处理相同的内容——我试图解析这些页面,以便我可以显示给定链接的内容片段(非常像 Facebook 分享)——如果一切都用 Beautiful Soup 完成,我想它会更快。
所以我的问题是:有没有办法使用 Beautiful Soup 来“清除标签”并用“纯文本”替换它们。如果没有,最好的方法是什么?
感谢您的建议!
更新: Alex 的代码在示例示例中运行良好。我还尝试了各种边缘情况,它们都运行良好(通过下面的修改)。所以我在一个真实的网站上试了一下,遇到了令我困惑的问题。
import urllib
from BeautifulSoup import BeautifulSoup
page = urllib.urlopen('http://www.engadget.com/2010/01/12/kingston-ssdnow-v-dips-to-30gb-size-lower-price/')
anchors = soup.findAll('a')
i = 0
for a in anchors:
print str(i) + ":" + str(a)
for a in anchors:
if (a.string is None): a.string = ''
if (a.previousSibling is None and a.nextSibling is None):
a.previousSibling = a.string
elif (a.previousSibling is None and a.nextSibling is not None):
a.nextSibling.replaceWith(a.string + a.nextSibling)
elif (a.previousSibling is not None and a.nextSibling is None):
a.previousSibling.replaceWith(a.previousSibling + a.string)
else:
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
a.nextSibling.extract()
i = i+1
当我运行上面的代码时,我收到以下错误:
0:<a href="http://www.switched.com/category/ces-2010">Stay up to date with
Switched's CES 2010 coverage</a>
Traceback (most recent call last):
File "parselink.py", line 44, in <module>
a.previousSibling.replaceWith(a.previousSibling + a.string + a.nextSibling)
TypeError: unsupported operand type(s) for +: 'Tag' and 'NavigableString'
当我查看 HTML 代码时,“保持最新..”没有任何以前的兄弟姐妹(在我看到 Alex 的代码之前,我没有以前的兄弟姐妹如何工作,并且根据我的测试,它看起来像是在寻找“文本”在标签之前)。所以,如果没有前一个兄弟姐妹,我很惊讶它没有经历 a.previousSibling 的 if 逻辑是 None 和 a;nextSibling 是 None。
你能告诉我我做错了什么吗?
-ecognium