用python写网络爬虫四:并发下载

由于本人对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中,所以先停止该测试,后续更新

性能对比

引用书中的对比图


用python写网络爬虫四:并发下载_第1张图片
性能对比.jpg

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

你可能感兴趣的:(用python写网络爬虫四:并发下载)