gaofeng0210 发表于 2015-4-21 10:40:15

使用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.iyunv.com(/|\w)+', str):
6               urlset.add(str + '\n')
7   return list(urlset)
  园里关于python的html解析的文章很多,看的我眼花缭乱,这里就不一一列举了。
  这里有个问题,我把match里的pattern改成 ’http://www.iyunv.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.iyunv.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.iyunv.com/\n'
61   content = getWebPage(starturl)
62   #urlset存放已访问过的网页url
63   #urllist存放待访问的网页url
64   urlset = set()
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会出问题,我也不知道什么原因,应该和网络有关。
  完
  
  
  
页: [1]
查看完整版本: 使用python多线程实现一个简单spider