昨晚发现放在腾讯云主机上通过crontab定时执行用以爬去斗鱼分类页面数据的爬虫在执行的时候速度特别慢,于是想通过多线程来提高效率。 打开浏览器,键入关键字“python 多线程”,发现大多数内容都是使用threading、Queue这些看起来很笨重的实例。不过直到multiprocessing.dummy出现在眼前之后,一切都变得辣么简单。

multiprocessing.dummy 与多线程

multiprocessing.dummy 是multiprocessing的一个子库,二者的不同之处就是前者应用于线程后者主要应用于进程,而它们实现并行化操作的关键则是map()函数。 以我的两段代码为例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
def insert_info():
    '''
    通过遍历游戏分类页面获取所有直播间
    '''
    session = requests.session()
    pagecontent = session.get(Directory_url).text
    pagesoup = BeautifulSoup(pagecontent)
    games = pagesoup.select('a')
    col.drop()
    for game in games:
        links = game["href"]
        Qurystr = "/?page=1&isAjax=1"
        gameurl = HOST + links + Qurystr
        gamedata = session.get(gameurl).text
        flag = get_roominfo(gamedata)
    aggregateData()

上边这段是之前运行在云主机速度真的跟爬似的代码,通过Directory_url这个地址,获取到页面中所有的标签,并获取到它们的’href',再逐条获取每个链接中的内容,获取想要的东西,最终完成入库工作。所有的一切都看似按部就班哈。在我的笔记本上做测试,完成所有2032条数据的爬取共耗时140.5s(好特么慢=。=)。

但是在加入multiprocessing.dummy之后,真的是有飞一般的感觉:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
from multiprocessing.dummy import Pool

pool = Pool()

def insert_info():
    '''
    通过遍历游戏分类页面获取所有直播间
    '''
    session = requests.session()
    pagecontent = session.get(Directory_url).text
    pagesoup = BeautifulSoup(pagecontent)
    games = pagesoup.select('a')
    gameurl = [HOST + url["href"] + "/?page=1&isAjax=1" for url in games]
    col.drop()
    g = lambda link: session.get(link).text
    gamedata = pool.map(g, gameurl)
    ginfo = lambda data: get_roominfo(data)
    pool.map(ginfo, gamedata)
    aggregateData()

同样通过Directory_url这一地址获取页面中所有标签,然后通过pool.map(g, gameurl)完成’href’值的获取,最后再用一次pool.map(ginfo,gamedata)完成所有页面内容的提取和入库。再一次测试,只需要33.1s即可完成。

更多详细信息可以参考官方文档