使用python多線程實現一個簡單spider


老習慣,先看看別人的工作。推薦看看 我的知識庫(1)--Java 搜索引擎的實現— 網絡爬蟲 文章把相關概念講的很詳細了。

老樣子,我也是初學者,通過本次學習主要掌握以下幾點:

1.了解python 網絡編程

2.了解python多線程鎖機制

3.掌握python re模塊match使用

那么開始吧

1.使用python抓取一個網頁的內容

使用urllib模塊

1 def getWebPage(url):
2     wp = urllib.urlopen(url)
3     content = wp.read()
4     return content

2.對抓取到的網頁內容進行分析,提取有用URL
抓到的數據是用str存儲的,下面使用python里的re.split()和re.match()

1 def analysisPage(content):
2     strlist = re.split('\"',content)
3     urlset = set([])
4     for str in strlist:
5         if re.match('http://www.cnblogs.com(/|\w)+', str):
6                 urlset.add(str + '\n')
7     return list(urlset)

園里關於python的html解析的文章很多,看的我眼花繚亂,這里就不一一列舉了。

這里有個問題,我把match里的pattern改成 ’http://www.cnblogs.com(/|\w)+html$' 就

匹配不出結果了,不知道什么原因,哪位大神知道。

3.多線程

主要用了一個urllist和一個urlset。

urlset用來存儲已經訪問過的網頁url,urllist用來存儲待訪問的網頁url

申請四個線程並行的對urllist的url進行頁面抽取,提取頁面url加入到urllist中

為了互斥使用urllist和urlset,引入了listlock和setlock兩把鎖

全部代碼如下:

 1 import re
 2 import urllib
 3 import threading
 4 
 5 def getWebPage(url):
 6     wp = urllib.urlopen(url)
 7     content = wp.read()
 8     return content
 9 
10 def analysisPage(content, urllist, urlset):
11     strlist = re.split('\"',content)
12     geturlset = set([])
13     for str in strlist:
14         if re.match('http://www.cnblogs.com/(/|\w)+', str):
15             geturlset.add(str + '\n')
16 
17     setlock.acquire()
18     geturlset = geturlset - urlset
19     setlock.release()
20 
21     listlock.acquire()
22     for url in list(geturlset):
23         urllist.append(url)
24     listlock.release()
25 
26 class MyThread(threading.Thread):
27     def __init__(self, urllist, urlset):
28         threading.Thread.__init__(self)
29         self.urllist = urllist
30         self.urlset = urlset
31 
32     def run(self):
33         while True:
34             listlock.acquire()
35             if self.urllist:
36                 url = self.urllist.pop(0)
37                 listlock.release()
38             else:
39                 listlock.release()
40                 break
41 
42             setlock.acquire()
43             if len(self.urlset) >= 50:
44                 setlock.release()
45                 break
46             else:
47                 if url in self.urlset:
48                     setlock.release()
49                     continue
50                 else:
51                     self.urlset.add(url)
52                     setlock.release()
53                     content = getWebPage(url)
54                     analysisPage(content, self.urllist, self.urlset)
55 
56 listlock = threading.RLock()
57 setlock = threading.RLock()
58 
59 if __name__ == '__main__':
60     starturl = 'http://www.cnblogs.com/\n'
61     content = getWebPage(starturl)
62     #urlset存放已訪問過的網頁url
63     #urllist存放待訪問的網頁url
64     urlset = set([starturl])
65     urllist = []
66     analysisPage(content, urllist, urlset)    
67     tlist = []
68     for i in range(4):
69         t = MyThread(urllist, urlset)
70         t.start()
71         tlist.append(t)
72     for t in tlist:
73         t.join()
74     f = open('url.txt', 'w')
75     f.writelines(list(urlset))
76     f.close()

當urlset集合的元素超過50時就停止,當這個數值較大時,socket會出問題,我也不知道什么原因,應該和網絡有關。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM