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

  • 相关阅读:
    【转】测试驱动开发
    【转】什么是“脚本语言”
    【转】“解决问题”与“消灭问题”
    【转】程序语言的常见设计错误(1)
    【转】解密“设计模式”
    【转】所谓软件工程
    【转】清华梦的粉碎
    算法知识目录整理
    买书不读是一种什么病?
    Linux 下socket通信终极指南(附TCP、UDP完整代码)
  • 原文地址:https://www.cnblogs.com/2010Freeze/p/2567389.html
Copyright © 2011-2022 走看看