使用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会出问题,我也不知道什么原因,应该和网络有关。

原文地址:https://www.cnblogs.com/2010Freeze/p/2567389.html