基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实现建立SSH连接的方法
Jun 03 Python
使用python在本地电脑上快速处理数据
Jun 22 Python
对python3中pathlib库的Path类的使用详解
Oct 14 Python
Python找出微信上删除你好友的人脚本写法
Nov 01 Python
python3实现表白神器
Apr 09 Python
python实现大量图片重命名
Mar 23 Python
python 实现屏幕录制示例
Dec 23 Python
python mysql中in参数化说明
Jun 05 Python
python实现录音功能(可随时停止录音)
Oct 26 Python
python 如何设置守护进程
Oct 29 Python
python opencv角点检测连线功能的实现代码
Nov 24 Python
FP-growth算法发现频繁项集——发现频繁项集
Jun 24 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
一个ORACLE分页程序,挺实用的.
2006/10/09 PHP
ASP和PHP都是可以删除自身的
2007/04/09 PHP
Ajax+PHP 边学边练 之二 实例
2009/11/24 PHP
基于PHP实现商品成交时发送短信功能
2016/05/11 PHP
PHP中文字符串截断无乱码解决方法
2016/10/10 PHP
LBS blog sql注射漏洞[All version]-官方已有补丁
2007/08/26 Javascript
让任务管理器中的CPU跳舞的js代码
2008/11/01 Javascript
固定表格行列(expression)在IE下适用
2013/07/25 Javascript
js清空form表单中的内容示例
2014/05/20 Javascript
JavaScript代码因逗号不规范导致IE不兼容的问题
2016/02/25 Javascript
JS脚本实现动态给标签控件添加事件的方法
2016/06/02 Javascript
JS实用的带停顿的逐行文本循环滚动效果实例
2016/11/23 Javascript
关于微信jssdk实现多图片上传的一点心得分享
2016/12/13 Javascript
js中字符型和数值型数字的互相转化方法(必看)
2017/04/25 Javascript
Vue 2.0入门基础知识之内部指令详解
2017/10/15 Javascript
JavaScript数据结构之优先队列与循环队列实例详解
2017/10/27 Javascript
vue拦截器实现统一token,并兼容IE9验证功能
2018/04/26 Javascript
使用validate.js实现表单数据提交前的验证方法
2018/09/04 Javascript
从零开始搭建vue移动端项目到上线的步骤
2018/10/15 Javascript
JavaScript错误处理操作实例详解
2019/01/04 Javascript
MockJs结合json-server模拟后台数据
2020/08/26 Javascript
小程序中this.setData的使用和注意事项
2019/08/28 Javascript
vue-router重写push方法,解决相同路径跳转报错问题
2020/08/07 Javascript
[48:48]完美世界DOTA2联赛PWL S3 Magama vs GXR 第一场 12.19
2020/12/24 DOTA
用Python实现命令行闹钟脚本实例
2016/09/05 Python
python实现飞机大战微信小游戏
2020/03/21 Python
Django项目中使用JWT的实现代码
2019/11/04 Python
python实现的批量分析xml标签中各个类别个数功能示例
2019/12/30 Python
python实现人机猜拳小游戏
2020/02/03 Python
Python selenium模块实现定位过程解析
2020/07/09 Python
比利时的在线灯具店:Lampen24.be
2019/07/01 全球购物
主要的Ajax框架都有什么
2013/11/14 面试题
vue 中 get / delete 传递数组参数方法
2021/03/23 Vue.js
党员学习十八大感想
2014/01/17 职场文书
低碳环保倡议书
2014/04/14 职场文书
无犯罪记录证明样本
2015/06/16 职场文书