基python实现多线程网页爬虫


Posted in Python onSeptember 06, 2015

一般来说,使用线程有两种模式, 一种是创建线程要执行的函数, 把这个函数传递进Thread对象里,让它来执行. 另一种是直接从Thread继承,创建一个新的class,把线程执行的代码放到这个新的class里。

实现多线程网页爬虫,采用了多线程和锁机制,实现了广度优先算法的网页爬虫。

先给大家简单介绍下我的实现思路:

对于一个网络爬虫,如果要按广度遍历的方式下载,它是这样的:

        1.从给定的入口网址把第一个网页下载下来

        2.从第一个网页中提取出所有新的网页地址,放入下载列表中

        3.按下载列表中的地址,下载所有新的网页

        4.从所有新的网页中找出没有下载过的网页地址,更新下载列表

        5.重复3、4两步,直到更新后的下载列表为空表时停止

python代码如下:

#!/usr/bin/env python
#coding=utf-8
import threading
import urllib
import re
import time
g_mutex=threading.Condition()
g_pages=[] #从中解析所有url链接
g_queueURL=[] #等待爬取的url链接列表
g_existURL=[] #已经爬取过的url链接列表
g_failedURL=[] #下载失败的url链接列表
g_totalcount=0 #下载过的页面数
class Crawler:
  def __init__(self,crawlername,url,threadnum):
    self.crawlername=crawlername
    self.url=url
    self.threadnum=threadnum
    self.threadpool=[]
    self.logfile=file("log.txt",'w')
  def craw(self):
    global g_queueURL
    g_queueURL.append(url)  
    depth=0
    print self.crawlername+" 启动..."
    while(len(g_queueURL)!=0):
      depth+=1
      print 'Searching depth ',depth,'...\n\n'
      self.logfile.write("URL:"+g_queueURL[0]+"........")
      self.downloadAll()
      self.updateQueueURL()
      content='\n>>>Depth '+str(depth)+':\n'
      self.logfile.write(content)
      i=0
      while i<len(g_queueURL):
        content=str(g_totalcount+i)+'->'+g_queueURL[i]+'\n'
        self.logfile.write(content)
        i+=1
  def downloadAll(self):
    global g_queueURL
    global g_totalcount
    i=0
    while i<len(g_queueURL):
      j=0
      while j<self.threadnum and i+j < len(g_queueURL):
        g_totalcount+=1
        threadresult=self.download(g_queueURL[i+j],str(g_totalcount)+'.html',j)
        if threadresult!=None:
          print 'Thread started:',i+j,'--File number =',g_totalcount
        j+=1
      i+=j
      for thread in self.threadpool:
        thread.join(30)
      threadpool=[]
    g_queueURL=[]
  def download(self,url,filename,tid):
    crawthread=CrawlerThread(url,filename,tid)
    self.threadpool.append(crawthread)
    crawthread.start()
  def updateQueueURL(self):
    global g_queueURL
    global g_existURL
    newUrlList=[]
    for content in g_pages:
      newUrlList+=self.getUrl(content)
    g_queueURL=list(set(newUrlList)-set(g_existURL))  
  def getUrl(self,content):
    reg=r'"(http://.+?)"'
    regob=re.compile(reg,re.DOTALL)
    urllist=regob.findall(content)
    return urllist
class CrawlerThread(threading.Thread):
  def __init__(self,url,filename,tid):
    threading.Thread.__init__(self)
    self.url=url
    self.filename=filename
    self.tid=tid
  def run(self):
    global g_mutex
    global g_failedURL
    global g_queueURL
    try:
      page=urllib.urlopen(self.url)
      html=page.read()
      fout=file(self.filename,'w')
      fout.write(html)
      fout.close()
    except Exception,e:
      g_mutex.acquire()
      g_existURL.append(self.url)
      g_failedURL.append(self.url)
      g_mutex.release()
      print 'Failed downloading and saving',self.url
      print e
      return None
    g_mutex.acquire()
    g_pages.append(html)
    g_existURL.append(self.url)
    g_mutex.release()
if __name__=="__main__":
  url=raw_input("请输入url入口:\n")
  threadnum=int(raw_input("设置线程数:"))
  crawlername="小小爬虫"
  crawler=Crawler(crawlername,url,threadnum)
  crawler.craw()

以上代码就是给大家分享的基python实现多线程网页爬虫,希望大家喜欢。

Python 相关文章推荐
python实现协同过滤推荐算法完整代码示例
Dec 15 Python
python实现Decorator模式实例代码
Feb 09 Python
Python中装饰器学习总结
Feb 10 Python
Python IDLE清空窗口的实例
Jun 25 Python
解决Python中定时任务线程无法自动退出的问题
Feb 18 Python
不到20行代码用Python做一个智能聊天机器人
Apr 19 Python
python 使用matplotlib 实现从文件中读取x,y坐标的可视化方法
Jul 04 Python
python logging模块的使用总结
Jul 09 Python
Django  ORM 练习题及答案
Jul 19 Python
Python imageio读取视频并进行编解码详解
Dec 10 Python
Python如何根据时间序列数据作图
May 12 Python
PyQt5.6+pycharm配置以及pyinstaller生成exe(小白教程)
Jun 02 Python
python杀死一个线程的方法
Sep 06 #Python
在Python的Flask框架中验证注册用户的Email的方法
Sep 02 #Python
Python实现身份证号码解析
Sep 01 #Python
实例Python处理XML文件的方法
Aug 31 #Python
通过实例浅析Python对比C语言的编程思想差异
Aug 30 #Python
使用Python脚本将文字转换为图片的实例分享
Aug 29 #Python
Python中常见的数据类型小结
Aug 29 #Python
You might like
php中的数组操作函数整理
2008/08/18 PHP
探讨如何使用SimpleXML函数来加载和解析XML文档
2013/06/07 PHP
PHP 极验验证码实例讲解
2016/09/29 PHP
PHP如何搭建百度Ueditor富文本编辑器
2018/09/21 PHP
PHP封装的数据库模型Model类完整示例【基于PDO】
2019/03/14 PHP
为Yahoo! UI Extensions Grid增加内置的可编辑器
2007/03/10 Javascript
jquery live()调用不存在的解决方法
2014/02/26 Javascript
javascript中拼接HTML字符串的最快、最好的方法
2014/06/07 Javascript
js识别不同浏览器基于userAgent做判断
2014/07/29 Javascript
基于编写jQuery的无缝滚动插件
2014/08/02 Javascript
常见的jQuery选择器汇总
2014/11/24 Javascript
jquery实现标签上移、下移、置顶
2015/04/26 Javascript
JavaScript中字符串(string)转json的2种方法
2015/06/25 Javascript
基于Jquery实现万圣节快乐特效
2015/11/01 Javascript
jQuery模拟物体自由落体运动(附演示与demo源码下载)
2016/01/21 Javascript
浅谈JS获取元素的N种方法及其动静态讨论
2017/08/25 Javascript
Vue项目中如何引入icon图标
2018/03/28 Javascript
如何能分清npm cnpm npx nvm
2019/01/17 Javascript
javascript 易错知识点实例小结
2020/04/25 Javascript
Object.keys() 和 Object.getOwnPropertyNames() 的区别详解
2020/05/21 Javascript
详解uniapp的全局变量实现方式
2021/01/11 Javascript
django框架之cookie/session的使用示例(小结)
2018/10/15 Python
在Python中,不用while和for循环遍历列表的实例
2019/02/20 Python
python 已知一个字符,在一个list中找出近似值或相似值实现模糊匹配
2020/02/29 Python
k-means 聚类算法与Python实现代码
2020/06/01 Python
通过canvas转换颜色为RGBA格式及性能问题的解决
2019/11/22 HTML / CSS
AmazeUI的JS表单验证框架实战示例分享
2020/08/21 HTML / CSS
J2EE面试题
2016/03/14 面试题
前台接待岗位职责
2013/12/03 职场文书
经典优秀个人求职信分享
2013/12/12 职场文书
交通事故协议书
2014/04/15 职场文书
动物科学专业求职信
2014/07/27 职场文书
住房抵押登记委托书
2014/09/27 职场文书
刑事辩护授权委托书格式
2014/10/13 职场文书
表扬信格式模板
2015/05/05 职场文书
警用民用对讲机找不同
2022/02/18 无线电