Beautifulsoup4与lxml对比Beautifulsoup3

时间:2012-07-02 16:39:42

标签: python profiling html-parsing beautifulsoup lxml

我正在将一些解析器从BeautifulSoup3迁移到BeautifulSoup4,我认为考虑到lxml速度超快而且它是我使用BS4的解析器,这将是一个好主意,这里是配置文件结果:

对于BS3:

43208 function calls (42654 primitive calls) in 0.103 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.000    0.000 <string>:2(<module>)
   18    0.000    0.000    0.000    0.000 <string>:8(__new__)
    1    0.000    0.000    0.072    0.072 <string>:9(parser)
   32    0.000    0.000    0.000    0.000 BeautifulSoup.py:1012(__init__)
    1    0.000    0.000    0.000    0.000 BeautifulSoup.py:1018(buildTagMap)
... 

对于使用lxml的BS4:

164440 function calls (163947 primitive calls) in 0.244 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.040    0.040    0.069    0.069 <string>:2(<module>)
   18    0.000    0.000    0.000    0.000 <string>:8(__new__)
    1    0.000    0.000    0.158    0.158 <string>:9(parser)
    1    0.000    0.000    0.008    0.008 HTMLParser.py:1(<module>)
    1    0.000    0.000    0.000    0.000 HTMLParser.py:54(HTMLParseError)
...

为什么BS4调用了4倍以上的函数?如果我将其设置为使用HTMLParser

,为什么它会使用lxml

我从BS3变为BS4的最引人注目的事情是:

 BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)  --->
 BeautifulSoup(html, 'lxml')

 [x.getText('**SEP**') for x in i.findChildren('font')[:2]] --->
 [x.getText('**SEP**', strip=True) for x in i.findChildren('font')[:2]]

其他一切只是一些名称更改(如findParent - &gt; find_parent)

编辑:

我的环境:

python 2.7.3
beautifulsoup4==4.1.0
lxml==2.3.4

编辑2:

这是一个试用它的小代码示例:

from cProfile import Profile

from BeautifulSoup import BeautifulSoup
from bs4 import BeautifulSoup as BS4
import urllib2


def parse(html):

    soup = BS4(html, 'lxml')
    hl = soup.find_all('span', {'class': 'mw-headline'})
    return [x.get_text(strip=True) for x in hl]


def parse3(html):

    soup = BeautifulSoup(html, convertEntities=BeautifulSoup.HTML_ENTITIES)
    hl = soup.findAll('span', {'class': 'mw-headline'})
    return [x.getText() for x in hl]


if __name__ == "__main__":
    opener = urllib2.build_opener()
    opener.addheaders = [('User-agent', 'Mozilla/5.0')]
    html = ''.join(opener.open('http://en.wikipedia.org/wiki/Price').readlines())

    profiler = Profile()
    print profiler.runcall(parse, html)
    profiler.print_stats()

    profiler2 = Profile()
    print profiler2.runcall(parse3, html)
    profiler2.print_stats()

1 个答案:

答案 0 :(得分:1)

我认为主要问题是Beautiful Soup 4中的一个错误。我已经filed it并且修补程序将在下一个版本中发布。谢谢你找到了这个。

那就是说,我不知道为什么你的个人资料会提到HTMLParser课程,因为你正在使用lxml。