11-抓取结果
[toc]
2.7 抓取结果
现在,我们已经完成所有爬虫代码的实现,接下来将通过如下代码片段,测试这3种方法的相对性能。代码中的导入操作期望你的目录结构与本书代码库相同,因此请根据需要进行调整。
import time
import re
from chp2.all_scrapers import re_scraper, bs_scraper,
lxml_scraper, lxml_xpath_scraper
from chp1.advanced_link_crawler import download
NUM_ITERATIONS = 1000 # number of times to test each scraper
html =
download('http://example.python-scraping.com/places/view/United-Kingdom-239')
scrapers = [
('Regular expressions', re_scraper),
('BeautifulSoup', bs_scraper),
('Lxml', lxml_scraper),
('Xpath', lxml_xpath_scraper)]
for name, scraper in scrapers:
# record start time of scrape
start = time.time()
for i in range(NUM_ITERATIONS):
if scraper == re_scraper:
re.purge()
result = scraper(html)
# check scraped result is as expected
assert result['area'] == '244,820 square kilometres'
# record end time of scrape and output the total
end = time.time()
print('%s: %.2f seconds' % (name, end - start))
在这段代码中,每个爬虫都会执行1000次,每次执行都会检查抓取结果是否正确,然后打印总用时。这里使用的 download 函数依然是上一章中定义的那个函数。请注意,我们在代码行中调用了 re.purge() 方法。默认情况下,正则表达式模块会缓存搜索结果,为了使其与其他爬虫的对比更加公平,我们需要使用该方法清除缓存。
下面是在我的计算机中运行该脚本的结果。
$ python chp2/test_scrapers.py
Regular expressions: 1.80 seconds
BeautifulSoup: 14.05 seconds
Lxml: 3.08 seconds
Xpath: 1.07 seconds
由于硬件条件的区别,不同计算机的执行结果也会存在一定差异。不过,每种方法之间的相对差异应当是相似的。从结果中可以看出,在抓取我们的示例网页时,Beautiful Soup的速度是其他方法的1/6。实际上这一结果是符合预期的,因为 lxml 和正则表达式模块都是C语言编写的,而 BeautifulSoup 则是纯Python编写的。一个有趣的事实是, lxml 表现得和正则表达式差不多好。由于 lxml 在搜索元素之前,必须将输入解析为内部格式,因此会产生额外的开销。而当抓取同一网页的多个特征时,这种初始化解析产生的开销就会降低, lxml 也就更具竞争力。正如我们在使用XPath解析器时所看到的, lxml 也可以直接使用正则表达式与之抗争。这真是一个令人惊叹的模块!
虽然我们强烈鼓励你使用 `lxml` 进行解析,不过网络抓取的最大性能瓶颈通常是网络。我们将会讨论并行工作流的方法,从而让你能够通过并行处理多个请求工作,来提升爬虫的速度。
虽然我们强烈鼓励你使用 `lxml` 进行解析,不过网络抓取的最大性能瓶颈通常是网络。我们将会讨论并行工作流的方法,从而让你能够通过并行处理多个请求工作,来提升爬虫的速度。