基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字符串的常用操作方法小结
May 21 Python
Python数据分析库pandas基本操作方法
Apr 08 Python
django1.11.1 models 数据库同步方法
May 30 Python
使用TensorFlow实现SVM
Sep 06 Python
idea创建springMVC框架和配置小文件的教程图解
Sep 18 Python
python字符串替换第一个字符串的方法
Jun 26 Python
python 中pyqt5 树节点点击实现多窗口切换问题
Jul 04 Python
Python中输入和输出(打印)数据实例方法
Oct 13 Python
浅谈sklearn中predict与predict_proba区别
Jun 28 Python
树莓派4B安装Tensorflow的方法步骤
Jul 16 Python
详解Anaconda 的安装教程
Sep 23 Python
opencv 分类白天与夜景视频的方法
Jun 05 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
基于mysql的论坛(2)
2006/10/09 PHP
利用递归把多维数组转为一维数组的函数
2006/10/09 PHP
php数组函数序列之asort() - 对数组的元素值进行升序排序,保持索引关系
2011/11/02 PHP
深入PHP获取随机数字和字母的方法详解
2013/06/06 PHP
浅析Mysql 数据回滚错误的解决方法
2013/08/05 PHP
thinkphp整合系列之极验滑动验证码geetest功能
2019/06/18 PHP
激活 ActiveX 控件
2006/10/09 Javascript
jqTransform form表单美化插件使用方法
2012/07/05 Javascript
原生js实现跨浏览器获取鼠标按键的值
2013/04/08 Javascript
javascript中加号(+)操作符的一些神奇作用
2014/06/06 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
javascript实现的简单计时器
2015/07/19 Javascript
Bootstrap+jfinal实现省市级联下拉菜单
2016/05/30 Javascript
BootStrap glyphicon图标无法显示的解决方法
2016/09/06 Javascript
详解Vue爬坑之vuex初识
2017/06/14 Javascript
javascript 判断用户有没有操作页面
2017/10/17 Javascript
vue中mint-ui的使用方法
2018/04/04 Javascript
vue2.0+koa2+mongodb实现注册登录
2018/04/10 Javascript
解决Layui数据表格中checkbox位置不居中的方法
2018/08/15 Javascript
详解React服务端渲染从入门到精通
2019/03/28 Javascript
Vue使用预渲染代替SSR的方法
2020/07/02 Javascript
vue组件入门知识全梳理
2020/09/21 Javascript
Python基于递归实现电话号码映射功能示例
2018/04/13 Python
django将数组传递给前台模板的方法
2019/08/06 Python
python 操作hive pyhs2方式
2019/12/21 Python
K近邻法(KNN)相关知识总结以及如何用python实现
2021/01/28 Python
Jupyter安装拓展nbextensions及解决官网下载慢的问题
2021/03/03 Python
初二学习计划书范文
2014/04/27 职场文书
计算机网络及管理学专业求职信
2014/06/05 职场文书
中学教师师德师风演讲稿
2014/08/22 职场文书
无房产证房屋转让协议书合同样本
2014/10/18 职场文书
难以忽视的真相观后感
2015/06/05 职场文书
大学学生会竞选稿
2015/11/19 职场文书
详解Spring Security中的HttpBasic登录验证模式
2022/03/17 Java/Android
redis 解决库存并发问题实现数量控制
2022/04/08 Redis
避坑之 JavaScript 中的toFixed()和正则表达式
2022/04/19 Javascript