1. 程式人生 > 其它 >Python爬蟲實戰入門六:提高爬蟲效率—併發爬取智聯招聘(轉載)

Python爬蟲實戰入門六:提高爬蟲效率—併發爬取智聯招聘(轉載)

之前文章中所介紹的爬蟲都是對單個URL進行解析和爬取,url數量少不費時,但是如果我們需要爬取的網頁url有成千上萬或者更多,那怎麼辦?
使用for迴圈對所有的url進行遍歷訪問?
嗯,想法很好,但是如果url過多,爬取完所有的資料會不會太過於耗時了?
對此我們可以使用併發來對URL進行訪問以爬取資料。
一般而言,在單機上我們使用三種併發方式:

  • 多執行緒(threading)
  • 多程序(multiprocessing)
  • 協程(gevent)

對於以上三種方法的具體概念解釋和說明,各位可以自行網上搜索瞭解,相信會比我解釋得清楚,所以在此就不對它們進行解釋說明了。
本系列文章有兩個重點,一個是實戰,一個是入門,既為實戰,理論性的東西就描述得比較少;既為入門,所講述的都是簡單易懂易操作的東西,高深的技術還請入門之後自行探索,那樣也會成長得更快。
那麼下面,開始併發爬取的實戰入門,以多程序為例,併發爬取智聯招聘的招聘資訊。
一、分析URL和頁面結構


1、搜尋全國範圍內職位名包含“Python”的職位招聘
我們不分職業類別、不分行業類別,工作地點選為全國,職位名為“Python”,對招聘資訊進行搜尋,結果如下圖:

我們注意圖中三個紅框的資訊:

  1. 搜尋結果的url結構;(構造url地址進行for迴圈遍歷)
  2. 搜尋結果的條數;(判斷url的數量)
  3. 採集的資訊的主體;(解析資料)

通過篩選url引數,我們確定了需要爬取的基本URL為:

http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&kt=3&p=2

其中

http://sou.zhaopin.com/jobs/searchresult.ashx
為請求地址和目錄

jl:工作地點引數
kw:搜尋的關鍵字
kt:以職位名搜尋
p:頁數

我們可以發現,除了頁數會變化之外,其餘的引數值都是固定的值。我們來確定一下搜尋結果的總頁數。
因為網頁上有提示一共有多少個職位滿足條件,我們拿總職位數除以單頁顯示的職位數量即可知道搜尋結果的頁數。

# coding:utf-8

import requests
from bs4 import BeautifulSoup
import re

url = 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&p=1&kt=3'
wbdata = requests.get(url).content
soup = BeautifulSoup(wbdata, 'lxml')

items = soup.select("div#newlist_list_content_table > table")
count = len(items) - 1
# 每頁職位資訊數量
print(count)

job_count = re.findall(r"共<em>(.*?)</em>個職位滿足條件", str(soup))[0]
# 搜尋結果頁數
pages = (int(job_count) // count) + 1
print(pages)

結果返回每頁60條職位資訊,一共有14頁。
那麼我們的待爬取的url地址就有14個,url地址中引數p的值分別從1到14,這麼少的url,使用for迴圈也可以很快完成,但在此我們使用多程序進行演示。
二、在爬蟲中使用多程序
先上程式碼:

# coding:utf-8

import requests
from bs4 import BeautifulSoup
from multiprocessing import Pool

def get_zhaopin(page):
    url = 'http://sou.zhaopin.com/jobs/searchresult.ashx?jl=全國&kw=python&p={0}&kt=3'.format(page)
    print("第{0}頁".format(page))
    wbdata = requests.get(url).content
    soup = BeautifulSoup(wbdata,'lxml')

    job_name = soup.select("table.newlist > tr > td.zwmc > div > a")
    salarys = soup.select("table.newlist > tr > td.zwyx")
    locations = soup.select("table.newlist > tr > td.gzdd")
    times = soup.select("table.newlist > tr > td.gxsj > span")

    for name, salary, location, time in zip(job_name, salarys, locations, times):
        data = {
            'name': name.get_text(),
            'salary': salary.get_text(),
            'location': location.get_text(),
            'time': time.get_text(),
        }
        print(data)

if __name__ == '__main__':
    pool = Pool(processes=2)
    pool.map_async(get_zhaopin,range(1,pages+1))
    pool.close()
    pool.join()

結果如下:

因為除了使用了多程序之外,其他的程式碼與之前文章介紹的方法大同小異,所以在此只介紹一下多程序的核心程式碼:

from multiprocessing import Pool

multiprocessing是Python自帶的一個多程序模組,在此我們使用其Pool方法。

if __name__ == '__main__':
    pool = Pool(processes=2)
    pool.map_async(get_zhaopin,range(1,pages+1))
    pool.close()
    pool.join()
  1. 例項化一個程序池,設定程序為2;
  2. 呼叫程序池的map_async()方法,接收一個函式(爬蟲函式)和一個列表(url列表)

如此,在爬蟲中使用多程序進行併發爬取就搞定了,更多高階、複雜強大的方法,還請各位參考其他文件資料。

文章版權所有: