python爬蟲——多進程multiprocessing

其實多進程相對來說不是特別適合用來做爬蟲,因爲多進程比較適用於計算密集型,而爬蟲是IO密集型,因此多進程爬蟲對速度的提升不是特別明顯,但是將爬蟲改爲多進程比較簡單,只需簡單的幾行代碼即可搞定,所以在修改我的爬蟲提升效率時,我最先實現的是多進程爬蟲。(然而速度真心還是慢,我多線程+協程的程序跑的晚,卻早已經結束工作了,多進程的還在苦戰…)
下面我通過實例來進行介紹。
我爬取的數據是外文數據庫的摘要信息,總共有幾百萬條記錄,因此我首先將抓取得到的url列表文件進行分割,減小對內存的壓力,免得全部加載佔用內存過高(昨天看了關於迭代器的內容,感覺如果使用迭代器的話,效果會更好一點,減少很多內存壓力,等我試水成功後再更新)。由於很多小夥伴可能沒有訪問外文數據庫的權限,因此我在此不把url數據上傳,對抓取的html頁面進行分析的內容也不放上來。主要介紹如何改造原有代碼爲多進程爬蟲。

#python2環境,3下差別不大
import requests
from bs4 import BeautifulSoup
import multiprocessing
import json
import datetime
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
path = sys.path[0] + '/data/'

多進程需要導入multiprocessing包。

def main():
    f = open(path + 'springerThesissList.txt', 'r')
    urlList = f.readlines() 
    pool = multiprocessing.Pool(3) #建立進程池,數字爲你cpu的核數,括號內可以爲空,程序會自動設定爲cpu最大核數。
    pool.map(getThesis, urllist) #將url傳入getThesis函數
def getThesis(url):
    """this is your code of scrap the url"""
if __name__ == '__main__':
    stime = datetime.datetime.now()
    print stime
    main()
    etime = datetime.datetime.now()
    print etime
    print etime - stime

getThesis(url)函數爲抓取url下內容的函數,可自定義。
通過main()函數中的短短兩行代碼,我們就可以將爬蟲改造成多進程爬蟲了,但是上面的方法有一個問題,就是得到的文件中會有這樣一種情況:當前行的內容還未寫入完畢,下一行的內容就已寫入。原因是多進程是併發執行函數,你在進程池中設立的數目爲3,則就有三個進程同時進行抓取,並訪問文件寫入數據,這樣就會出現上面的問題。可以通過下面的方法進行解決。

def main():
    listf = open(path + 'springerThesisList.txt', 'r')
    urlList = listf.readlines()
    pool = multiprocessing.Pool(3)
    for url in urllist:
        result = pool.apply_async(getThesis, (url, ), callback = jsonDump)
    pool.close()
    pool.join()
    if result.successful():
        print "successful"

jsonDump函數爲我自定義的寫入json數據的函數。此處將其作爲回調函數對getThesis函數的返回結果進行處理。因此getThesis函數與之前的也略有不同,之前不需要該函數有返回值,但是在此處則需將其進行修改,在函數末尾加入一行代碼,返回此函數抓取到的數據。因爲在函數中我使用了try except來增強代碼的容錯性,因此返回值有可能爲空,因此在jsonDump函數中,需要先判斷dic是否爲空。

outf = open(path + 'springerThesis.json', 'a')
def jsonDump(dic):
    if dic:
        json.dump(dic, outf, ensure_ascii=False)
        outf.write('\n')
def getThesis(url):
    """this is your code of scrap the url"""
    #×××
    #×××
    return dic

到此爲止,基本上講清楚瞭如何在爬蟲中使用多進程。有問題歡迎評論交流。
接下來我會介紹如何在爬蟲中使用多線程和協程來提高爬蟲的速度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章