本來這周準備寫乙個整合ip池,多程序的高效爬取所有職位詳細資訊的爬蟲的,結果在多程序這一塊兒折騰了好久,簡直把我氣死,雖然內容其實不多,但把自己學習的過程寫下來,希望能幫到有同樣困惑的朋友。
實現多工最常見的兩種方式就是多程序和多執行緒了。多程序,顧名思義,多個程序併發執行,可以有效提高程式的執行效率,優點是非常穩定,即使有子程序崩潰了,主程序和其他程序依然可以繼續執行,但缺點是在windows下建立程序的開銷比較大,而且如果程序太多,往往會影響整個系統的排程。而多執行緒是指乙個程序內多個執行緒同時執行,進而提高程式執行效率,其優點可能是比多程序稍微快一點,但缺點也很明顯,多執行緒中乙個執行緒出現了問題就會導致整個程序崩潰,因此穩定性不是很高。
然後由於python直譯器在執行**是有乙個gil鎖(global interpreter lock),它的作用是任何python程序執行前都必須先獲得gil鎖,然後沒執行100條位元組碼釋放gil鎖,讓別的程序有機會執行,因此多執行緒在python中只能交替執行,所以針對改善我們的爬蟲程式,我們選擇使用多程序的方法。
在windows系統下,python可以通過multiprocessing庫實現多程序,先從最簡單地開啟乙個子程序開始
from multiprocessing import process
import os
def run_proc(name):
print 'run child process %s (%s) ' %(name,os.getpid())
if __name__=='__main__':
print 'parent process %s ' %os.getpid()
p=process(target=run_proc,args=('test',))
print 'process will start'
p.start()
p.join()
print 'process end'
在上面的**中,我們定義了乙個函式用於輸出當前程序的id,然後利用multiprocessing中的process函式新建乙個程序,start()函式用於啟動程序,join()函式用於子程序執行完後再向下執行,然而結果並不如預料那般
子程序似乎沒有執行,在這個地方我花費了很長時間,一直在想哪兒有問題,最後證明**確實沒問題,問題在於多程序這個操作在ide裡似乎無法執行,所以我又換到命令列裡執行以下。這裡提示一下,win7或者問win10在資料夾裡,按住shift郵件就會出現開啟命令列,python yourfile.py 即可執行,上述程式結果如下:
我們可以看到成功地開啟了乙個新程序,好的,第一步完成了,那下一步是如何同時開啟多個程序呢?別急,multiprocessing模組中還提供了pool物件,可以同時開啟多個程序,乙個簡單的測試**如下
from multiprocessing import pool
import time
import os
def task(name):
print 'run task %s (%s)...'%(name,os.getpid())
print time.time()
time.sleep(3)
if __name__=='__main__':
print 'parent process %s'%os.getpid()
p=pool()
for i in range(9):
print 'waiting for all subprocess done ...'
p.close()
p.join()
print 'all subprocess done'
在這裡我們定義了乙個task函式,用於輸出當前程序的id和當前程序開始的時間,然後建立了乙個pool物件,它可以引入processes引數來指定同時啟動程序的數量,預設的是你機器的核心數。join()函式用於等待所有子程序執行完畢,而join()函式之前必須引用close()函式來禁止新的程序的建立,執行結果如下
我們可以看到前面八個程序幾乎是同時開始的,而最後乙個程序是在有乙個程序結束之後(等待3s)開始的,因為我機器的核心數是8,所以這很合乎常理。到這裡,我們對python中多程序的使用已經有一定的認識了,下一步就是應用到我們的ip驗證當中了,其實方法和我們的測試程式一模一樣,我們把之前獲取可用ip位址的函式拆分成乙個獲取所有**的函式和乙個驗證函式,方便我們進行多程序的操作,通過單程序執行和多程序執行,我們比較多程序方法引入帶來效率的提高,具體實現**如下
# -*- coding: utf-8 -*-
"""__author__='cd'
"""import requests
from bs4 import beautifulsoup
import csv
import time
from multiprocessing import pool
def getip(numpage):
csvfile = file('ips.csv', 'wb')
writer = csv.writer(csvfile)
url=''
user_agent='ip'
headers=
for i in xrange(1,numpage+1):
real_url=url+str(i)
response=requests.get(real_url,headers=headers)
content=response.text
bs=beautifulsoup(content)
trs=bs.find_all('tr')
for items in trs:
tds=items.find_all('td')
temp=
try:
writer.writerow(temp)
except:
pass
getip(1)
def getproxy():
reader=csv.reader(open('ips.csv'))
proxy=
for row in reader:
proxy=
return proxy
def test(proxy):
try:
response=requests.get('',proxies=proxy,timeout=2)
if response:
return proxy
except:
pass
if __name__=='__main__':
proxy=getproxy()
ippool1=
time1=time.time()
for item in proxy:
time2=time.time()
print 'singleprocess needs '+str(time2-time1)+' s'
pool=pool()
ippool2=
temp=
time3=time.time()
for item in proxy:
pool.close()
pool.join()
for item in temp:
time4=time.time()
print 'multiprocess needs '+str(time4-time3)+' s'
在這個程式裡,我們只爬取了第一頁的ip並進行了驗證結果如下
可以看到,採用多程序之後,驗證的時間縮短了8倍,這是因為我採用了預設的設定,同一時間的程序數為我機器的核心數是8,如果將程序數進一步提高可以獲得更快的速度,當然速度的減小並不是線性的,肯定後面效果越來越差,因為程序的切換需要時間,多程序也增加了系統排程的難度等等。
好了,利用python的多程序來減小**ip驗證所需時間的技能get到了,當然完全可以舉一反三,因為爬蟲本來就是個io密集型的工作,所以我們在爬取網頁時同樣也可以使用多程序來減小等待時間,哈哈哈,真開心~
Python中的多程序
編寫完的 沒有執行時稱為程式,正在執行的 稱為程序。程式是死的 靜態的 程序是活的 動態的 作業系統輪流讓各個任務交替執行,由於cpu的執行速度實在是太快了,我們感覺就像所有任務都在同時執行一樣。多程序中,每個程序中所有資料 包括全域性變數 都各自擁有乙份,互不影響。例如 我們啟動了qq,qq就是乙...
python中的多程序
import multiprocessing import time deffunc arg pname multiprocessing.current process name pid multiprocessing.current process pid print 當前程序id d,name ...
python中的多程序運用
from multiprocessing import process from os import getpid from time import sleep defrun time name sleep 5 print child progress format name,getpid if n...