像CSS选择器一样使用BeautifulSoup

53 views
Skip to first unread message

jeff jie

unread,
Jun 15, 2009, 11:04:05 PM6/15/09
to pyth...@googlegroups.com, zp...@googlegroups.com
共享一些代码片段,一直说要共享,一搁就大半年。。哎。。

较早前写扒虫多,虽然BeautifulSoup很好用,但厌倦每次都要手动去编写复杂的Dom元素定位语句,突然想,能不能像CSS选择器一样,只给一个表达式就返回我想要的东西?后来在网上找了下没找着,想了想工作量也不大就自己实现了一个,目前支持ID,Class,标签及属性选择器、支持 space、 >、 + 操作符,基本上已满足大部份定位需求。

代码见附件的BTSelector.py,另附UnitTest。
常见使用方式是:
注意,本脚本依赖于BeautifulSoup,所以,使用之前请确保你已经安装了。


from BTSelector import findAll
soup = BeautifulSoup(htmlContent)
nodes = findAll('div.navigator #notice',soup)
# findAll返回的是符合选择条件的Dom 对象列表,实际上是BeautifulSoup的标签或字符类。

除了使用findAll函数,还可以直接使用findById,findByTag等函数,等有兴趣的同学看源代码来发现了。

用testCase作为使用示例:
一、上一个复杂一点的用例:
def testMixSelection(self):

        target = "#header > div#name > a.highlight"

        html = '''

        <div id="header">

            <div id="name">

                <a class="target">test</a>

                <a class="highlight">right</a>

                <a class="highlight">ok</a>

            </div>

            <div id="your">

            </div>

        </div>

        <div id="body">fk

        </div>

        '''

        soup = BeautifulSoup(html)

        ret = findAll(target,soup)

        self.assertEqual(2,len(ret))



二、再上一个使用位置操作符的用例:
def testPosition(self):

        target = "h2 + ul > li > a"

        html = '''

        <h2>title</h2>

        <ul>

            <li><a href="#">nothing</a></li>

            <li><a href="#">ok</a></li>

            <li><a href="#">come on!</a></li>

        </ul>

        '''

        soup = BeautifulSoup(html)

        ret = findAll(target,soup)

        self.assertEqual(3,len(ret))



更多的见附件的Unittest。里面没太多技术含量的东西,但希望大家喜欢。

BTSelector.zip

@@

unread,
Jun 15, 2009, 11:08:11 PM6/15/09
to pyth...@googlegroups.com
多谢分享 有机会尝试下。

现在用的是lxml 的xpath来做 也还不错 不过就怕碰见不规范的直接解析就出错了。。



2009/6/16 jeff jie <bbm...@gmail.com>

flya flya

unread,
Jun 15, 2009, 11:08:58 PM6/15/09
to pyth...@googlegroups.com
太好了,强烈支持,我也一直想写个这种东西。

2009/6/16 jeff jie <bbm...@gmail.com>



--
http://www.flyaflya.com

金浩

unread,
Jun 15, 2009, 11:10:45 PM6/15/09
to pyth...@googlegroups.com
其实,这个东西类似应该已经有了。比如pyquery http://pyquery.org/
 
另外听很多人说 BeautifulSoup 效率非常差。

当然,还是非常感谢LZ分享。

 
2009/6/16 jeff jie <bbm...@gmail.com>

iXh

unread,
Jun 15, 2009, 11:15:29 PM6/15/09
to pyth...@googlegroups.com
我现在正在写爬虫
希望有点帮助
我现在还是处于原始阶段
筛选标签还是自己用正则

2009/6/16 金浩 <jinha...@gmail.com>

jeff jie

unread,
Jun 15, 2009, 11:16:19 PM6/15/09
to pyth...@googlegroups.com
pyquery的网站打开一踏糊涂捏。。firefox 和 safari.

BeautifulSoup效率差不差见仁见智,也看使用的场合。扒虫类的应用的瓶颈更多是在网络链接方面的延迟。

2009/6/16 金浩 <jinha...@gmail.com>

金浩

unread,
Jun 15, 2009, 11:27:32 PM6/15/09
to pyth...@googlegroups.com
不会吧, http://pyquery.org/ 网站的首页就是项目的文档页,又没有什么特别的,怎么可能显示错乱。

2009/6/16 jeff jie <bbm...@gmail.com>

smallfish_xy

unread,
Jun 15, 2009, 11:30:22 PM6/15/09
to pyth...@googlegroups.com

袁雁波

unread,
Jun 15, 2009, 11:40:56 PM6/15/09
to pyth...@googlegroups.com
可以用twisted,把网络延时改为异步调用,这样可能会提高效率

2009/6/16 jeff jie <bbm...@gmail.com>

jeff jie

unread,
Jun 15, 2009, 11:53:19 PM6/15/09
to pyth...@googlegroups.com
截个图吧,我也不知道,我的操作系统是mac os。换回windows正常的。
pyquery的确很牛,我当时也就想找一个jquery 的serverside语言实现,可能是现在这个原因找不开页面而错过了。。呵呵。
pyquery用途超越了扒虫范围不少呢,不过对于习惯用BTFSoup的同学们来讲,BTSelector还是很理想的选择。。嘿。

2009/6/16 金浩 <jinha...@gmail.com>
Picture.jpg

Zoom.Quiet

unread,
Jun 16, 2009, 12:03:29 AM6/16/09
to pyth...@googlegroups.com
2009/6/16 金浩 <jinha...@gmail.com>:

> 其实,这个东西类似应该已经有了。比如pyquery http://pyquery.org/
>
> 另外听很多人说 BeautifulSoup 效率非常差。

听说的怎么靠谱哪,自个儿体验才准

--
http://zoomquiet.org
'''过程改进乃是催生可促生靠谱的人的组织!'''
usage 7-zip to replace WinRAR/WinZip; You can get the truely Freedom 4 software.

金浩

unread,
Jun 16, 2009, 12:13:22 AM6/16/09
to pyth...@googlegroups.com
恩,是啊,不过因为没什么大规模数据处理的经验,所以即使用了也感觉不出什么性能差别。
 
不过,BeautifulSoup 对中文编码以及乱标签的的支持其实不如他所宣传的那样好。
尤其是对乱标签,有时候还会丢失本来就是想解析出来的那部分数据。
2009/6/16 Zoom.Quiet <zoom....@gmail.com>

jeff jie

unread,
Jun 16, 2009, 12:23:30 AM6/16/09
to pyth...@googlegroups.com
我扒过几十G的数据,出错率极低,不过对效率没太大要求,但还是用线程和队列来做还是很有必要的。
BeautifulSoup的编码支持还可以,有时会不准,具体解决方案可以参考这边篇日志的字符编码部份 http://www.fallever.com/?p=109

另外,乱标签的问题,如果对BeautifulSoup没信心,在解释之前用tidy tidy一下吧。。

2009/6/16 金浩 <jinha...@gmail.com>

Zoom.Quiet

unread,
Jun 16, 2009, 2:50:44 AM6/16/09
to zp...@googlegroups.com, pyth...@googlegroups.com
2009/6/16 jeff jie <bbm...@gmail.com>:

赞的!
收录在:
http://wiki.woodpecker.org.cn/moin/MiscItems/2009-06-16

代码分享在:
http://code.google.com/p/zqlib/source/browse/tangle/BTSelector/


--
http://zoomquiet.org
'''过程改进乃是催生可促生靠谱的人的组织!'''
Free as in Freedom! 哲思自由软件社区:http://zeuux.org

Victor Lin

unread,
Jun 16, 2009, 3:05:26 AM6/16/09
to python-cn`CPyUG`华蟒用户组(中文Py用户组)
我原本也以為瓶頸會是在網路
但BeautifulSoup效率很差,當數量多到一定程度
CPU就會滿載,我用profile跑過
顯示出它的find系列函數效率極差

改用lxml + xpath之後改善了好幾倍的效能

On 6月16日, 上午11時16分, jeff jie <bbm...@gmail.com> wrote:
> pyquery的网站打开一踏糊涂捏。。firefox 和 safari.
> BeautifulSoup效率差不差见仁见智,也看使用的场合。扒虫类的应用的瓶颈更多是在网络链接方面的延迟。
>

> 2009/6/16 金浩 <jinhao7...@gmail.com>
>
> > 其实,这个东西类似应该已经有了。比如pyqueryhttp://pyquery.org/

Zoom.Quiet

unread,
Jun 16, 2009, 3:35:47 AM6/16/09
to pyth...@googlegroups.com
2009/6/16 Victor Lin <Born...@gmail.com>:

> 我原本也以為瓶頸會是在網路
> 但BeautifulSoup效率很差,當數量多到一定程度
> CPU就會滿載,我用profile跑過
> 顯示出它的find系列函數效率極差
>
> 改用lxml + xpath之後改善了好幾倍的效能
>
用 lxml 的前题是得 XHTML 的内容吧,当前中国网站中流行的 HTML 很难解析的

--

Heroboy

unread,
Jun 16, 2009, 4:17:48 AM6/16/09
to pyth...@googlegroups.com
BeautifulSoup 解析 <a a=">">a</a> 错误

Victor Lin

unread,
Jun 16, 2009, 4:34:17 AM6/16/09
to python-cn`CPyUG`华蟒用户组(中文Py用户组)
lxml 可以解html 甚至可以和BeautifulSoup做整合的樣子,自從我改用lxml就沒在碰過BeautifulSoup

On 6月16日, 下午3時35分, "Zoom.Quiet" <zoom.qu...@gmail.com> wrote:
> 2009/6/16 Victor Lin <Borns...@gmail.com>:> 我原本也以為瓶頸會是在網路

> --http://zoomquiet.org

shell909090

unread,
Jun 16, 2009, 5:40:42 AM6/16/09
to pyth...@googlegroups.com
使用的结果,至少我处理的网页多数都可以。
但是对于一些特别不规范的网页还是不行。

Victor Lin 写道:

Zoom.Quiet

unread,
Jun 16, 2009, 5:49:58 AM6/16/09
to pyth...@googlegroups.com
2009/6/16 Victor Lin <Born...@gmail.com>:
> lxml 可以解html 甚至可以和BeautifulSoup做整合的樣子,自從我改用lxml就沒在碰過BeautifulSoup
>
那么这个小工具也可以迁移到 lxml 上了哪

--
http://zoomquiet.org
'''过程改进乃是催生可促生靠谱的人的组织!'''
金山常年招聘Py/C++人才! http://bit.ly/UoTV 简历直投俺就成;-)

金浩

unread,
Jun 16, 2009, 5:53:52 AM6/16/09
to pyth...@googlegroups.com
pyquery 好像就是基于 lxml 的。

2009/6/16 Zoom.Quiet <zoom....@gmail.com>

smallfish_xy

unread,
Jun 16, 2009, 5:55:45 AM6/16/09
to pyth...@googlegroups.com
官方第一句:pyquery uses lxml for fast xml and html manipulation.
2009/6/16 金浩 <jinha...@gmail.com>
pyquery 好像就是基于 lxml 的。

jeff jie

unread,
Jun 16, 2009, 6:19:14 AM6/16/09
to pyth...@googlegroups.com
长见识了。。得再了解下lxml。有空可以多出一个lxml的版本。。

2009/6/16 smallfish_xy <smallf...@gmail.com>

jeff jie

unread,
Jun 16, 2009, 10:30:08 AM6/16/09
to pyth...@googlegroups.com
我果然火星了,lxml已经提供一个cssselector的类了,用法如下:
>>> from lxml import etree, cssselect
>>> select = cssselect.CSSSelector("a tag > child")

>>> root = etree.XML("<a><b><c/><tag><child>TEXT</child></tag></b></a>")
>>> [ el.tag for el in select(root) ]
['child']
使用Lxml的同学好幸福啊!本贴也显得有重复发明轮子之嫌了。不过对偏爱美丽的汤的同学来说,本贴还是多余得有点价值了,哈。

2009/6/16 jeff jie <bbm...@gmail.com>

@@

unread,
Jun 16, 2009, 10:38:41 AM6/16/09
to pyth...@googlegroups.com
汗。。一直没发现有这个。。

还跑去费劲尝试用xpath。。

2009/6/16 jeff jie <bbm...@gmail.com>

iXh

unread,
Jun 16, 2009, 10:42:52 AM6/16/09
to pyth...@googlegroups.com
 楼主这个小白鼠当得值得
学习了
^_^

2009/6/16 @@ <ask...@gmail.com>

kenvin

unread,
Jun 21, 2009, 2:47:36 AM6/21/09
to pyth...@googlegroups.com
有两个问题:
1. 纯python 的东西,效率是个问题。
2. 对不标准的html,能正常运行吗


2009/6/16 iXh <ixh.x...@gmail.com>
Reply all
Reply to author
Forward
0 new messages