匯入第3方庫:
from bs4 import beautifulsoup
from spider.extra import utils
from multiprocessing import process,value,joinablequeue,manager,pool
import threading
import argparse
from fake_useragent import useragent
import time,random,requests
定義爬蟲程序:
class spiderwork(process):
def __init__(self,q,res_q,complete_num,begin_time,proxy_list,proxytime):
super().__init__()
self.q = q
self.res_q = res_q
self.complete_num = complete_num
self.proxy_list = proxy_list
self.init_time = time.time()
self.begin_time = begin_time
self.proxytime = proxytime
def run(self):
while true:
url = self.q.get()
self.crawl_url(url)
self.q.task_done()
def crawl_url(self,url):
if time.time() - self.init_time > self.proxytime:
self.init_time = time.time()
self.proxy_list = utils.get_proxy_every_15_min()
soup = beautifulsoup(self.gethtmltext(url), 'html.parser')
try:
down_href = soup.select('#down_url > li:nth-child(2) > a')[0]
self.res_q.put((url, down_href["href"]))
self.complete_num.value += 1
if self.complete_num.value % 40 == 0:
time_span = time.time() - self.begin_time
print("------完成數量:%d,用時:%d秒------\n" % (self.complete_num.value, time_span))
except:
def gethtmltext(self,url):
retry_time = 0
res = ''
while true:
proxy = random.choice(self.proxy_list)
ua = useragent(use_cache_server=false)
try:
headers = ,url:,當前重試次數----')
res = r.text
break
except:
retry_time += 1
print(f'----**失效,url:,當前重試次數----')
if retry_time > 20:
print(f'----url:,當前重試次數大於20,爬取失敗----')
break
return res
定義寫程序,用來訪問爬到的結果:
def writefile_job(done_md5_file,res_q):
while true:
res = res_q.get()
print(f'------')
with open('exe_result.txt', 'a', encoding='utf-8') as fw:
fw.write(res[1]+'\n')
with open(done_md5_file, 'a', encoding='utf-8') as fw:
fw.write(res[0]+'\n')
res_q.task_done()
程式入口**,接受3個引數:
file-儲存待爬取url的文字路徑,格式一行乙個url
proxytime-**更新時間,使用**防止被封
cpunum-開啟的程序個數,預設是cpu的核心數
parser = argparse.argumentparser(description='crawl virustotal')
parser.add_argument('--file','-f',required=true)
parser.add_argument('--proxytime','-p',type=int,default=900)
parser.add_argument('--cpunum','-c',type=int,default=os.cpu_count())
args = parser.parse_args()
cpu_num = args.cpunum if args.cpunum < os.cpu_count() else os.cpu_count()
url_file = args.file
載入待爬取的所有url:
urls =
with open(url_file, 'r', encoding='utf-8') as fr:
for line in fr.readlines():
line = line.replace("\n", "")
if len(line)>0:
讀取已完成的url,計算待爬取的url,用來處理程式中斷後,可以從中斷處繼續爬取:
done_url_file = os.path.splitext(url_file)[0]+ '_done.txt'
done_url = #讀取已爬取完成的md5
if os.path.isfile(done_url_file):
with open(done_url_file, 'r') as fr:
for line in fr.readlines():
line = line.replace("\n", "")
if len(line) > 0:
#計算未爬取的md5
undone_url = list(set(urls) - set(done_url))
print(f'檢測到已完成的url有:個')
print(f'重新計算需要爬取的url個數,為:個')
將待爬取的url放入佇列,多程序從佇列中取url:
q = joinablequeue()
for url in undone_url:
q.put(url)
獲取**,新建乙個佇列用來儲存爬取結果:
proxy_list = utils.get_proxy_every_15_min()
begin_time = time.time()
res_q = joinablequeue()
開啟多個程序,從佇列讀取url爬取,同時開啟乙個執行緒,一直從儲存結果的返回佇列讀出資料,並儲存:
with manager() as mg:
complete_num = value('i', 0)
for i in range(cpu_num):
p = spiderwork(q,res_q,complete_num,begin_time,proxy_list,args.proxytime)
p.daemon = true #主程序結束,程序結果,故設為守護程序
p.start()
wr_td = threading.thread(target=writefile_job, args=(done_url_file,res_q,))
wr_td.setdaemon(true) #主程序結束,執行緒結果,故設為守護程序
wr_td.start()
q.join() #等待佇列中url全部爬取完成
res_q.join() #等待返回佇列中結果全部處理完成
end_time = time.time()
print(f'原始urls:')
print(f'完成數量:')
print(f'用時:')
python多程序卡住 python多程序假死
結論 python多程序間用queue通訊時,如果子程序操作queue滿了或者內容比較大的情況下,該子程序會阻塞等待取走queue內容 如果queue資料量比較少,不會等待 如果呼叫join,主程序將處於等待,等待子程序結束,造成死鎖 解決方式 在呼叫join前,及時把queue的資料取出,而且qu...
多程序爬蟲
1.多程序爬貓眼電影 下圖是爬去後的結果 在寫爬蟲的時候,資料量大的時候,所需要的時間就會很長,所以今天就來說多程序爬資料,有興趣的可以執行下面的 coding utf 8 import sys reload sys sys.setdefaultencoding utf 8 import reque...
Python 學習筆記 多程序爬蟲
前段時間學習了多執行緒,但在實際的情況中對於多執行緒的速度實在不滿意,所以今天就來學學多程序分布式爬蟲,在這裡感謝莫煩的python教程。在講述多程序之前,先來回顧一下之前學習的多執行緒。對於多執行緒可以簡單的理解成運輸快遞的貨車,雖然在整個運輸快遞的途中有很多貨車參與運輸,但快遞到你手中的時間並不...