如何使用BeautifulSoup模拟":contains"?

NT3*_*3RP 5 python google-app-engine beautifulsoup

我正在做一个我需要抓一点的项目.该项目位于Google App Engine上,我们目前正在使用Python 2.5.理想情况下,我们会使用PyQuery,但由于在App Engine和Python 2.5上运行,这不是一个选项.

我已经看过像这样的问题,找到带有特定文本的HTML标签,但它们并没有达到标准.

我有一些看起来像这样的HTML:

<div class="post">
    <div class="description">
        This post is about <a href="http://www.wikipedia.org">Wikipedia.org</a>
    </div>
</div>
<!-- More posts of similar format -->
Run Code Online (Sandbox Code Playgroud)

在PyQuery中,我可以做这样的事情(据我所知):

s = pq(html)
s(".post:contains('This post is about Wikipedia.org')")
# returns all posts containing that text
Run Code Online (Sandbox Code Playgroud)

天真的,我曾经在BeautifulSoup中做过这样的事情:

soup = BeautifulSoup(html)
soup.findAll(True, "post", text=("This post is about Google.com"))
# []
Run Code Online (Sandbox Code Playgroud)

但是,这没有产生任何结果.我改变了我的查询以使用正则表达式,并得到了更多,但仍然没有运气:

soup.findAll(True, "post", text=re.compile(".*This post is about.*Google.com.*"))
# []
Run Code Online (Sandbox Code Playgroud)

如果省略Google.com,它可以工作,但我需要手动完成所有过滤.无论如何:contains使用BeautifulSoup 模拟?

或者,是否有一些类似PyQuery的库可以在App Engine上运行(在Python 2.5上)?

Ste*_*sop 5

来自BeautifulSoup文档(强调我的):

"text是一个允许您搜索NavigableString对象 而不是 Tags的参数"

也就是说,你的代码:

soup.findAll(True, "post", text=re.compile(".*This post is about.*Google.com.*"))
Run Code Online (Sandbox Code Playgroud)

不一样:

regex = re.compile('.*This post is about.*Google.com.*')
[post for post in soup.findAll(True, 'post') if regex.match(post.text)]
Run Code Online (Sandbox Code Playgroud)

您必须删除Google.com的原因是BeautifulSoup树中有一个NavigableString对象"This post is about",另一个用于"Google.com",但它们位于不同的元素下.

顺便说一句,post.text存在但没有记录,所以我也不会依赖它,我偶然写了那段代码!使用其他一些方法将所有文本放在一起post.