python支持多线程的爬虫实例


Posted in Python onDecember 21, 2019

python是支持多线程的, 主要是通过thread和threading这两个模块来实现的,本文主要给大家分享python实现多线程网页爬虫

一般来说,使用线程有两种模式, 一种是创建线程要执行的函数, 把这个函数传递进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使用chardet判断字符串编码的方法
Mar 13 Python
Python生成不重复随机值的方法
May 11 Python
Python Requests模拟登录实现图书馆座位自动预约
Apr 27 Python
Django unittest 设置跳过某些case的方法
Dec 26 Python
python实现微信自动回复机器人功能
Jul 11 Python
让Python脚本暂停执行的几种方法(小结)
Jul 11 Python
Python closure闭包解释及其注意点详解
Aug 28 Python
python绘制分布折线图的示例
Sep 24 Python
pymongo insert_many 批量插入的实例
Dec 05 Python
Jupyter Notebook 远程访问配置详解
Jan 11 Python
Python趣味挑战之给幼儿园弟弟生成1000道算术题
May 28 Python
Python Matplotlib绘制动画的代码详解
May 30 Python
Python 实现try重新执行
Dec 21 #Python
在python shell中运行python文件的实现
Dec 21 #Python
Python 脚本的三种执行方式小结
Dec 21 #Python
python带参数打包exe及调用方式
Dec 21 #Python
python脚本后台执行方式
Dec 21 #Python
Python模块的制作方法实例分析
Dec 21 #Python
基于Python 中函数的 收集参数 机制
Dec 21 #Python
You might like
使用VisualStudio开发php的图文设置方法
2010/08/21 PHP
php递归遍历多维数组的方法
2015/04/18 PHP
24条货真价实的PHP代码优化技巧
2016/07/28 PHP
PHP实现的折半查找算法示例
2017/12/19 PHP
javascript 进度条 实现代码
2009/07/30 Javascript
JQuery Tips(2) 关于$()包装集你不知道的
2009/12/14 Javascript
JS保留两位小数,多位小数的示例代码
2014/01/07 Javascript
一个JavaScript用逗号分割字符串实例
2014/09/22 Javascript
JS实现至少包含字母、大小写数字、字符的密码等级的两种方法
2015/02/03 Javascript
js动态创建及移除div的方法
2015/06/03 Javascript
Ionic实现仿通讯录点击滑动及$ionicscrolldelegate使用分析
2016/01/18 Javascript
jQuery Mobile页面返回不需要重新get
2016/04/26 Javascript
url中的特殊符号有什么含义(推荐)
2016/06/17 Javascript
js与applet相互调用的方法
2016/06/22 Javascript
jQuery layui常用方法介绍
2016/07/25 Javascript
angular2倒计时组件使用详解
2017/01/12 Javascript
基于JavaScript实现的快速排序算法分析
2017/04/14 Javascript
基于jQuery实现文字打印动态效果
2017/04/21 jQuery
JavaScript选择排序算法原理与实现方法示例
2018/08/06 Javascript
vue移动端屏幕适配详解
2019/04/30 Javascript
Node.js fs模块(文件模块)创建、删除目录(文件)读取写入文件流的方法
2019/09/03 Javascript
微信小程序开发之转发分享功能
2019/10/22 Javascript
vue-element-admin 菜单标签失效的解决方式
2019/11/12 Javascript
Vue左滑组件slider使用详解
2020/08/21 Javascript
python中bisect模块用法实例
2014/09/25 Python
django 通过ajax完成邮箱用户注册、激活账号的方法
2018/04/17 Python
Python3 使用cookiejar管理cookie的方法
2018/12/28 Python
对Python的交互模式和直接运行.py文件的区别详解
2019/06/29 Python
keras自定义损失函数并且模型加载的写法介绍
2020/06/15 Python
基于Python实现全自动下载抖音视频
2020/11/06 Python
纯HTML5+CSS3制作图片旋转
2016/01/12 HTML / CSS
Html5 实现微信分享及自定义内容的流程
2019/08/20 HTML / CSS
优秀的2014年两会精神解读
2014/03/17 职场文书
红领巾广播站广播稿(3篇)
2014/09/20 职场文书
mysql事务对效率的影响分析总结
2021/10/24 MySQL
Python用any()函数检查字符串中的字母以及如何使用all()函数
2022/04/14 Python