由于本人对mongoDB不太熟悉,所以《用python写网络爬虫四:并发下载》中的代码去除了相关mongoDB的相关代码
通过http://s3.amazonaws.com/alexa-static/top-1m.csv.zip 下载alexa数据表由于链接是外网,而且还有错误问题,所以我的方法是下下载在通过本地aip包去找到所有的url,返回urls,由于网址大多需要外网链接,所以也没有用到,alexa_cb代码如下
#!/usr/bin/env python
# -*-coding:utf-8 -*-
from zipfile import ZipFile
import csv
class AlexaCallback:
def __init__(self, max_urls=500):
self.max_urls=max_urls
self.seed_url = 'http://s3.amazonaws.com/alexa-static/top-1m.csv.zip'
def __call__(self):
urls = []
#使用zipfile解压文件
with ZipFile('alexadoc.zip', 'r') as zf:
csv_filename = zf.namelist()[0]
for _, website in csv.reader(zf.open(csv_filename)):
if len(urls)< self.max_urls:
urls.append('http://'+website)
else:
print '已到500'
break
return urls
#测试
if __name__ == '__main__':
a = AlexaCallback()
s = a()
for ss in s:
print ss
请求网页页面downloader
使用request请求
#!/usr/bin/env python
# -*-coding:utf-8 -*-
import requests
class Downloader:
def __init__(self):
pass
def __call__(self, url):
try:
response = requests.get(url)
except Exception, e:
print url, e
return {'url': url, 'code': '808','html': ""}
# return {'html': response.text, 'code': response.status_code}
return {'url': url, 'code': response.status_code,'html': response.text}
串行爬虫
由于链接是外网的原因,我将urls改为http://www.baidu.com
使用time 的lock方法计算运行时间
测试代码运行时间链接
#!/usr/bin/env python
# -*-coding:utf-8 -*-
from alexa_cb import AlexaCallback
from downloader import Downloader
from time import clock
import time
def main():
# alexa = AlexaCallback()
downloader = Downloader()
# urls = alexa()
urls = ['http://www.baidu.com'] * 100
for url in urls:
time.sleep(1)
dict_url=downloader(url)
if __name__ == '__main__':
start = clock()
print 'start..........'
main()
finish = clock()
print 'stop............'
print (finish - start)
多线程爬虫:
使用多线程爬取速度会更快,但是开辟线程数也不是越多越好,
代码如下
#!/usr/bin/env python
# -*-coding:utf-8 -*-
import threading
from downloader import Downloader
import time
def main(max_threads=10):
print '...'
# alexa = AlexaCallback()
downloader = Downloader()
# urls = alexa()
urls = ['http://www.baidu.com'] * 100
thrads =[]
def down():
while urls:
time.sleep(1)
if len(urls) > 0:
dict_url = downloader(urls.pop())
else:
break
while urls:
if len(thrads) < max_threads:
t = threading.Thread(target=down)
t.start()
thrads.append(t)
if __name__ == '__main__':
start = time.clock()
print 'start..........'
main()
finish = time.clock()
print 'stop............'
print (finish - start)
测试结果:
由于我程序中使用了请求间隔是1s所以串行爬虫103.771557655,多线程爬虫开辟线程10个运行时间是10.1964406335,所以多线程爬虫的效率要比串行爬虫好的多
多进程爬虫
由于是进程,不能同时作用于一个变量,需要存储在mongoDB中,所以先停止该测试,后续更新
性能对比
引用书中的对比图

可以看出 , 性能的增长与线程和进程的数量并不是成线性 比例 的 , 而是趋于对数。 比如 , 使用 1个进程和 5 个线程时, 性能大约为 串行时的 4 倍, 而使用 20 个线程时性能只达到了 串行下载时的 10 倍。 虽然新增的线程能够加快下载速度, 但是起到的效果相 比于之前添加 的线程会越来越小 。 其实这是可 以预见到的现象, 因为
此时进程需要在更多线程之间进行切换, 专 门用于每一个线程的时间就会变少。 此外, 下载的带宽是有限的 , 最终添加新线程将无法带来更快的下载速度 。 因此, 要想获得更好的性能, 就需要在多 台服务器上分布式部署爬虫,并且所有服务器都要指向 同一个 MongoDB 队列实例 。