之前寫的爬蟲都是單個執行緒的,一旦某個地方卡住不動了,那就要演員等待下去了,所以我們可以使用多執行緒或多程序來處理
但是我個人不建議用,不過 還是簡單的介紹下
爬蟲使用多執行緒來處理網路請求,使用執行緒來處理url佇列中的url,然後將url返回的結果儲存在另乙個佇列中,其它執行緒在讀取這個佇列中的資料,然後寫到檔案中去3.1 url佇列和結果佇列
將要爬取的url放在乙個佇列中,這裡使用標準庫queue,訪問url後的結果儲存在結果佇列中
初始化乙個url佇列
from queue import queue
url_queue=
queue()
html_queue=
queue
()
3.2 請求執行緒
使用多個執行緒,不停的取url佇列中的url,並進行處理:
from threading import thread
class
threadinfo
(thread)
: def __init__
(self,url_queue,html_queue)
: thread.
__init__
(self)
self.url_queue=url_queue
self.html_queue=html_queue
def run
(self)
: user_agents =[,
"user-agent:mozilla/5.0(windowsnt6.1;rv:2.0.1)gecko/20100101firefox/4.0.1",]
headers =
while self.url_queue.
empty()
==false:
url=self.url_queue.
get(
) response = requests.
get(url,headers=headers)
if response.status_code==
200:
self.html_queue.
put(response.text)
如果隊列為空,執行緒就會被阻塞,知道佇列不為空,處理佇列中的一條資料後,就需要通知佇列已經這條資料處理完
3.3 處理執行緒
處理結果佇列中的資料,並儲存到檔案中,如果使用多個執行緒的話必須要給檔案加上鎖
lock=threading.
lock()
f=codecs.
open
('xiaohua.txt'
,'w'
,'utf-8'
)
當執行緒需要寫入檔案的時候,可以這樣處理:
with lock:
f.write
(something)
這裡舉乙個爬取糗事百科的段子的例子,
from threading import thread
from queue import queue
from lxml import etree
from random import choice
import requests
#爬蟲類
class
crawlinfo
(thread)
: def __init__
(self,url_queue,html_queue)
: thread.
__init__
(self)
self.url_queue=url_queue
self.html_queue=html_queue
def run
(self)
: user_agents =[,
"user-agent:mozilla/5.0(windowsnt6.1;rv:2.0.1)gecko/20100101firefox/4.0.1",]
headers =
while self.url_queue.
empty()
==false:#url佇列不為空的時候
url=self.url_queue.
get(
) response = requests.
get(url,headers=headers)
if response.status_code==
200:
self.html_queue.
put(response.text)
#解析類
class
parseinfo
(thread)
: def __init__
(self,html_queue)
: thread.
__init__
(self)
self.html_queue=html_queue
def run
(self)
:while self.html_queue.
empty()
==false:
e = etree.
html
(self.html_queue.
get())
span_list=e.
xpath
('//div[@class="content"]/span[1]'
)with
open
('xiaohua.txt'
,'a'
,encoding=
'utf-8'
)as f:
for span in span_list:
info=span.
xpath
('string(.)'
) f.
write
(info+
'\n'
)if __name__==
'__main__'
: url_queue=
queue
()#用來儲存url的容器
base_url=
""html_queue=
queue
()#用來儲存爬取到的整個頁面的html,還未解析
for i in
range(1
,14):
new_url=base_url.
format
(i)print
(new_url)
url_queue.
put(new_url)
crawl_list=
#用來放爬蟲類的執行緒,因為下面要讓3個執行緒都等待,所以需要存起來
for i in
range(0
,3):#建立3個執行緒
crawl1=
crawlinfo
(url_queue,html_queue)
crawl_list.
(crawl1)
crawl1.
start()
for crawl in crawl_list:
crawl.
join()
parse_list=
for i in
range(0
,3):
parse=
parseinfo
(html_queue)
parse_list.
(parse)
parse.
start()
for parse in parse_list:
parse.
join
()
Boost之多執行緒
c 標準庫沒有涉及執行緒,在c 中,雖然不可能寫出標準相容的多執行緒程式,程式設計師可以使用特定作業系統提供的執行緒庫來寫出多執行緒程式來。可是,這至 少導致兩個突出的問題 作業系統普遍提供的是c庫,在c 中使用要更小心,每個作業系統都有自己的一套支援多執行緒的庫 另外,不標準,不可移植。boost...
linux之多執行緒
linux系統下的多執行緒遵循posix執行緒介面,稱為pthread 標頭檔案 include 原型 int pthread create pthread t tidp,const pthread attr t attr,void start rtn void void arg 返回值 若執行緒建...
c 之多執行緒
1.對多執行緒的呼叫用到頭檔案 1.1中的操縱函式 pthread create pthread t tidp,constpthread attr t attr,void start rtn void void arg 第乙個引數為指向執行緒 識別符號的 指標。第二個引數用來設定執行緒屬性。第三個引...