python中怎么實現(xiàn)一個多線程爬蟲

這篇文章給大家介紹python中怎么實現(xiàn)一個多線程爬蟲,內(nèi)容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

站在用戶的角度思考問題,與客戶深入溝通,找到?jīng)錾街菥W(wǎng)站設(shè)計與涼山州網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗,讓設(shè)計與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個性化、用戶體驗好的作品,建站類型包括:網(wǎng)站制作、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣、域名注冊、虛擬主機、企業(yè)郵箱。業(yè)務(wù)覆蓋涼山州地區(qū)。

開發(fā)環(huán)境:

ubuntu16.04,python3.6,bs4,virtualenv(虛擬環(huán)境)

創(chuàng)建虛擬環(huán)境:

創(chuàng)建項目文件夾,并為項目創(chuàng)建虛擬環(huán)境,利用pip安裝相關(guān)包

mkdir mutiThreadCrawier
cd  mutiThreadCrawier
mkdir content #存爬下來的頁面
virtualenv env --python =python3.6 #創(chuàng)建虛擬環(huán)境
source env/bin/activate   #使虛擬環(huán)境生效

導(dǎo)包:

import time
import re
import threading
import urllib
import requests
from bs4 import BeautifulSoup

定義變量

g_mutex = threading.Condition()  # 可以加鎖/釋放鎖
print(g_mutex)
print(type(g_mutex))
g_urls = []  # 存放解析出來的url對應(yīng)的網(wǎng)頁源碼
g_queue_urls = [] # 待爬取的url
g_exist_urls = []  # 已經(jīng)爬過的url
g_failed_urls = [] # 失敗的鏈接
g_total_count = 0  # 已經(jīng)下載的頁面的計數(shù)器

定義線程類:

創(chuàng)建一個線程類,繼承于threading.Thread,并進構(gòu)造,在run函數(shù)中根據(jù)url路徑請求網(wǎng)絡(luò)連接,并保存頁面html文檔保存到本地,如果下載失敗則拋出異常。并將下載過頁面的路由添加到g_exist_urls

class CrawlerThread(threading.Thread):


   def __init__(self,url,filename,tid):
       threading.Thread.__init__(self)
       self.filename=filename
       self.url =url
       self.tid=tid
   def run(self):
       try:
           resp=urllib.request.urlopen(self.url)
           html=resp.read()
           with open('content/'+self.filename,'wb') as f:

               f.write(html)
       except Exception as e:
           g_exist_urls.append(self.url)
           g_failed_urls.append(self.url)
           print(f'頁面{self.url}下載失??!')
       g_mutex.acquire()
       g_urls.append(html)
       g_exist_urls.append(self.url)
       g_mutex.release()

定義爬蟲類:

對其進行構(gòu)造,創(chuàng)建日志,download()函數(shù)創(chuàng)建線程,update_queque_url對連接的列表進行更新,get_url()根據(jù)bs4進行匹配獲取連接,download_all()通過調(diào)用download()函數(shù)實現(xiàn)批量下載。spider作為一個入口函數(shù)進行爬取

class Crawler:
   def __init__(self,name,domain,thread_number):
       self.name=name

       self.domain=domain
       self.thread_number=thread_number

       self.logfile=open('log.txt','w')
       self.thread_pool=[]
       self.url = 'http://'+domain

    def spider(self):# 內(nèi)容會隨著爬蟲的進行而更新
       global g_queue_urls# 初始,隊列中僅有一個url
       g_queue_urls.append(self.url)# 爬取的深度
       depth =0
       print(f'爬蟲{self.name}開始啟動........')
       while g_queue_urls:
           depth +=1
           print(f'當(dāng)前爬取深度是{depth}')
           self.logfile.write(f'URL:{g_queue_urls[0]}')
           self.download_all() # 下載所有
           self.update_queque_url() # 更新 url隊列
           self.logfile.write(f">>>Depth:{depth}")
           count = 0
           while count <len(g_queue_urls):
               self.logfile.write(f"累計爬取{g_total_count}條,爬取是第{g_queue_urls[count]}個")
               count+=1



   def download_all(self):
       global g_queue_urls
       global g_total_count
       i=0
       while i < len(g_queue_urls):
           j=0
           while j<self.thread_number and i+j <len(g_queue_urls):
               g_total_count +=1
               print(g_queue_urls[i+j])
               thread_result=self.download(g_queue_urls[i+j],f"{g_total_count}.html",j)
               if thread_result  is not None:
                     print(f'線程{i+j}啟動')
               j +=1
           i=i+j
           for thread in self.thread_pool:
               thread.join(25)
       g_queue_urls=[]



   def download(self,url,filename,tid):
       print(url,filename,tid)
       creawler_thread= CrawlerThread(url,filename,tid)
       self.thread_pool.append(creawler_thread)
       creawler_thread.start()
   def update_queque_url(self):
       global g_queue_urls
       global g_exist_urls#已經(jīng)爬過的url
       new_urls=[]#新發(fā)現(xiàn)的url
       for url_content in g_urls:
           new_urls +=self.get_Url(url_content)# 從頁面中提取新url
       g_queue_urls=list(set(new_urls)  -set(g_exist_urls)) # 去除重復(fù)的和已經(jīng)爬過的

   def get_Url(self,content):
    '''
       從網(wǎng)頁源代碼中提取url
       '''
       links =[] # 保存提取到的href
       try:

           soup =BeautifulSoup(content)
           for link in soup.findAll('a'):
               if link is not None and link.get('href') is not None:
                   if self.domain in link['href']:
# 如果link是本網(wǎng)站的絕對地址
                       links.append(link)
                   elif  len(link['href']) >10 and  'http://' not in link['href']:
# 如果link是相對地址
                       links.append(self.url +link['href'])



       except Exception as e:
           print("fail to get url",e)
       return links

主函數(shù)

主函數(shù)調(diào)用爬蟲函數(shù)的spider()方法

if __name__=="__main__":
   domain ="www.geyanw.com"
   thread_number=10
   name="geyan"
   crawler =Crawler(name,domain,thread_number)
   crawler.spider()

關(guān)于python中怎么實現(xiàn)一個多線程爬蟲就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

分享名稱:python中怎么實現(xiàn)一個多線程爬蟲
分享路徑:http://bm7419.com/article40/jceoho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、網(wǎng)站設(shè)計公司、網(wǎng)站營銷、網(wǎng)站建設(shè)、外貿(mào)建站、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)