python函數式實現的多線程抓取樣本

來源:互聯網
上載者:User

寫的一個爬蟲練習,目的是抓取目標網站下所有連結, 並記錄下問題連結url(包括問題url,入口連結,http狀態代碼)。可以自行設定線程數量,程式開啟一個子線程來維護當前線程數量。之前還好點兒,現在是越改bug越多,問題越多。
目前發現的問題有:
1.線程的管理上,之前用傳統的方法,三個for迴圈來建立固定數量線程,不過發現如果某線程拋出異常後,線程終止,匯流排程數就會減少。所以自己改成了用一個死迴圈不停的監聽活動線程數量。發現執行過程中,線程name的數量不斷增長,每一個建立的線程在執行完一次方法後好像就退出了。。。
2.url_new列表儲存待抓取的url,發現還是有重複的現象。 感覺用函數式的線程實現的話,線程間的同步好像不太好。。
3.lock有問題。。。因為自己還是沒有掌握lock的鎖法,發現url有重複時,自己把整個def都用lock鎖了起來。。 還是問題不斷啊。。
4.目標站還是寫死在程式中。。。
待改進為物件導向!

 代碼如下 複製代碼

#encoding: gb2312
import urllib2
import threading
import logging
import re
import sys
import os
from bs4 import BeautifulSoup
reload(sys)
sys.setdefaultencoding("utf-8")
#日誌初始化
FILE = os.getcwd()
logging.basicConfig(filename=os.path.join(FILE, 'log.txt'),level=logging.DEBUG)
#待抓取的任務隊列
url_new = [('none','http://www.111cn.net/')]
#已完成的任務
url_old = []
#已完成的狀態
url_err = {200:[]}
#鎖
lock = threading.Lock()
lock2= threading.Lock()

#線程執行主方法
#從工作清單中擷取一條url進行抓取
#分析url,去重複,將得到的urls重新放入工作清單
#儲存當前url的訪問狀態
def geturl():
    global url_new
    try:
        while True:
            lock.acquire()
            if len(url_new)<=0:
                lock.release()
                continue
            url_t = url_new.pop(0)
            url = url_t[1]
            try:
                req = urllib2.urlopen(url)
            except urllib2.HTTPError, e:
                #記錄到對應的列表中
                if url_err.has_key(e.code):
                    url_err[e.code].append((url,url_t[0]))
                else:
                    url_err[e.code] = [(url,url_t[0])]
                with open('log.html', 'a+') as f:
                        f.write(str(e.code)+':'+url+', 來路:'+url_t[0]+'<br>')
                        continue
            else:
                url_err[200].append(url)
                with open('log.html', 'a+') as f:
                        f.write('200:'+url+', 來路:'+url_t[0]+'<br>')
           
            #記錄到已訪問的列表中
            url_old.append(url)
            #開始提取頁面url
            soup = BeautifulSoup(req.read().decode('UTF-8', 'ignore'))
            alink= soup.find_all('a', attrs={'href':re.compile(".*?xxxxxx.*?")})
            tmp_url = []
            for a in alink:
                href = a.get('href')
                tmp_url.append(a.get('href') if a.get('href').find('http:')>=0 else 'http://www.xxxxxx.com'+a.get('href'))
            tmp_url= {}.fromkeys(tmp_url).keys()
            for link in tmp_url:
                if link not in url_old:
                    url_new.append((url, link))
            tmp = []
            for i in xrange(len(url_new)):
                if url_new[i][1] not in tmp:
                    tmp.append(url_new[i][1])
                else:
                    del url_new[i]
               
            #url_new = {}.fromkeys(url_new).keys()

            #輸出一下狀態資訊
            os.system('cls')
            print threading.Thread().getName()+":當前線程數:"+str(threading.activeCount())+",當前剩餘任務量:"+str(len(url_new))+", 已訪問:"+str(len(url_old))
            for k in url_err.keys():
                print str(k)+':'+str(len(url_err[k]))

            lock.release()
    except Exception as e:
        logging.debug(str(e))
        lock.release()

 

#線程數檢測 死迴圈持續檢測當前活動線程數
#不夠數量時自動建立啟動新線程
def threadcheck(num):
    t=threading.Thread(target=geturl)
    t.start()
    t.join()


#定義主方法
def main():
    """初始 建立200個線程
    for i in xrange(190):
        t = threading.Thread(target=geturl)
        threads.append(t)
    for i in xrange(190):
        threads[i].start()
    for i in xrange(190):
        threads[i].join()"""
    t = threading.Thread(target=threadcheck, args=(10,))
    t.start()
    t.join()
    #geturl(url_new.pop(0))

#開始
if __name__ == '__main__':
    main()
input('整站抓取已結束!')

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.