深入理解Python分布式爬虫原理


Posted in Python onNovember 23, 2017

首先,我们先来看看,如果是人正常的行为,是如何获取网页内容的。

(1)打开浏览器,输入URL,打开源网页

(2)选取我们想要的内容,包括标题,作者,摘要,正文等信息

(3)存储到硬盘中

上面的三个过程,映射到技术层面上,其实就是:网络请求,抓取结构化数据,数据存储。

我们使用Python写一个简单的程序,实现上面的简单抓取功能。

#!/usr/bin/python 
#-*- coding: utf-8 -*- 
''''' 
Created on 2014-03-16 
 
@author: Kris 
''' 
import urllib2, re, cookielib 
 
def httpCrawler(url): 
  ''''' 
  @summary: 网页抓取 
  ''' 
  content = httpRequest(url) 
  title = parseHtml(content) 
  saveData(title) 
 
def httpRequest(url): 
  ''''' 
  @summary: 网络请求 
  '''  
  try: 
    ret = None 
    SockFile = None 
    request = urllib2.Request(url) 
    request.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)') 
    request.add_header('Pragma', 'no-cache') 
    opener = urllib2.build_opener() 
    SockFile = opener.open(request) 
    ret = SockFile.read() 
  finally: 
    if SockFile: 
      SockFile.close() 
     
  return ret 
 
def parseHtml(html): 
  ''''' 
  @summary: 抓取结构化数据 
  ''' 
  content = None 
  pattern = '<title>([^<]*?)</title>' 
  temp = re.findall(pattern, html) 
  if temp: 
    content = temp[0] 
   
  return content 
   
def saveData(data): 
  ''''' 
  @summary: 数据存储 
  ''' 
  f = open('test', 'wb') 
  f.write(data) 
  f.close() 
   
if __name__ == '__main__': 
  url = 'http://www.baidu.com' 
  httpCrawler(url)

看着很简单,是的,它就是一个爬虫入门的基础程序。当然,在实现一个采集过程,无非就是上面的几个基础步骤。但是实现一个强大的采集过程,你会遇到下面的问题:

(1)需要带着cookie信息访问,比如大多数的社交化软件,基本上都是需要用户登录之后,才能看到有价值的东西,其实很简单,我们可以使用Python提供的cookielib模块,实现每次访问都带着源网站给的cookie信息去访问,这样只要我们成功模拟了登录,爬虫处于登录状态,那么我们就可以采集到登录用户看到的一切信息了。下面是使用cookie对httpRequest()方法的修改:

ckjar = cookielib.MozillaCookieJar() 
cookies = urllib2.HTTPCookieProcessor(ckjar)     #定义cookies对象 
def httpRequest(url): 
  ''''' 
  @summary: 网络请求 
  '''  
  try: 
    ret = None 
    SockFile = None 
    request = urllib2.Request(url) 
    request.add_header('User-Agent', 'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322)') 
    request.add_header('Pragma', 'no-cache') 
    opener = urllib2.build_opener(cookies)    #传递cookies对象 
    SockFile = opener.open(request) 
    ret = SockFile.read() 
  finally: 
    if SockFile: 
      SockFile.close() 
     
  return ret

(2)编码问题。网站目前最多的两种编码:utf-8,或者gbk,当我们采集回来源网站编码和我们数据库存储的编码不一致时,比如,163.com的编码使用的是gbk,而我们需要存储的是utf-8编码的数据,那么我们可以使用Python中提供的encode()和decode()方法进行转换,比如:

content = content.decode('gbk', 'ignore')   #将gbk编码转为unicode编码 
content = content.encode('utf-8', 'ignore')  #将unicode编码转为utf-8编码

中间出现了unicode编码,我们需要转为中间编码unicode,才能向gbk或者utf-8转换。

(3)网页中标签不完整,比如有些源代码中出现了起始标签,但没有结束标签,HTML标签不完整,就会影响我们抓取结构化数据,我们可以通过Python的BeautifulSoup模块,先对源代码进行清洗,再分析获取内容。

(4)某些网站使用JS来生存网页内容。当我们直接查看源代码的时候,发现是一堆让人头疼的JS代码。可以使用mozilla、webkit等可以解析浏览器的工具包解析js、ajax,虽然速度会稍微慢点。

(5)图片是flash形式存在的。当图片中的内容是文字或者数字组成的字符,那这个就比较好办,我们只要利用ocr技术,就能实现自动识别了,但是如果是flash链接,我们将整个URL存储起来了。

(6)一个网页出现多个网页结构的情况,这样我们如果只是一套抓取规则,那肯定不行,所以需要配置多套模拟进行协助配合抓取。

(7)应对源网站的监控。抓取别人的东西,毕竟是不太好的事情,所以一般网站都会有针对爬虫禁止访问的限制。
一个好的采集系统,应该是,不管我们的目标数据在何处,只要是用户能够看到的,我们都能采集回来。所见即所得的无阻拦式采集,无论是否需要登录的数据都能够顺利采集。大部分有价值的信息,一般都需要登录才能看到,比如社交网站,为了应对登录的网站要有模拟用户登录的爬虫系统,才能正常获取数据。不过社会化网站都希望自己形成一个闭环,不愿意把数据放到站外,这种系统也不会像新闻等内容那么开放的让人获取。这些社会化网站大部分会采取一些限制防止机器人爬虫系统爬取数据,一般一个账号爬取不了多久就会被检测出来被禁止访问了。那是不是我们就不能爬取这些网站的数据呢?肯定不是这样的,只要社会化网站不关闭网页访问,正常人能够访问的数据,我们也能访问。说到底就是模拟人的正常行为操作,专业一点叫“反监控”。

源网站一般会有下面几种限制:

1、一定时间内单个IP访问次数,一个正常用户访问网站,除非是随意的点着玩,否则不会在一段持续时间内过快访问一个网站,持续时间也不会太长。这个问题好办,我们可以采用大量不规则代理IP形成一个代理池,随机从代理池中选择代理,模拟访问。代理IP有两种,透明代理和匿名代理。

2、一定时间内单个账号访问次数,如果一个人一天24小时都在访问一个数据接口,而且速度非常快,那就有可能是机器人了。我们可以采用大量行为正常的账号,行为正常就是普通人怎么在社交网站上操作,并且单位时间内,访问URL数目尽量减少,可以在每次访问中间间隔一段时间,这个时间间隔可以是一个随机值,即每次访问完一个URL,随机随眠一段时间,再接着访问下一个URL。

如果能把账号和IP的访问策略控制好了,基本就没什么问题了。当然对方网站也会有运维会调整策略,敌我双方的一场较量,爬虫必须要能感知到对方的反监控将会对我们有影响,通知管理员及时处理。其实最理想的是能够通过机器学习,智能的实现反监控对抗,实现不间断地抓取。

下面是本人近期正在设计的一个分布式爬虫架构图,如图1所示:

深入理解Python分布式爬虫原理

纯属拙作,初步思路正在实现,正在搭建服务器和客户端之间的通信,主要使用了Python的Socket模块实现服务器端和客户端的通信。如果有兴趣,可以单独和我联系,共同探讨完成更优的方案。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python映射拆分操作符用法实例
May 19 Python
Python简单检测文本类型的2种方法【基于文件头及cchardet库】
Sep 18 Python
Python搜索引擎实现原理和方法
Nov 27 Python
python2.7+selenium2实现淘宝滑块自动认证功能
Feb 24 Python
使用python获取csv文本的某行或某列数据的实例
Apr 03 Python
python3 cvs将数据读取为字典的方法
Dec 22 Python
python多进程读图提取特征存npy
May 21 Python
将Python文件打包成.EXE可执行文件的方法
Aug 11 Python
python numpy中cumsum的用法详解
Oct 17 Python
Spring Boot中使用IntelliJ IDEA插件EasyCode一键生成代码详细方法
Mar 20 Python
MxNet预训练模型到Pytorch模型的转换方式
May 25 Python
django restframework serializer 增加自定义字段操作
Jul 15 Python
Python实现希尔排序算法的原理与用法实例分析
Nov 23 #Python
Python 用Redis简单实现分布式爬虫的方法
Nov 23 #Python
Python3 伪装浏览器的方法示例
Nov 23 #Python
python学习笔记之列表(list)与元组(tuple)详解
Nov 23 #Python
python数字图像处理之高级滤波代码详解
Nov 23 #Python
Python3网络爬虫之使用User Agent和代理IP隐藏身份
Nov 23 #Python
python网络爬虫之如何伪装逃过反爬虫程序的方法
Nov 23 #Python
You might like
php更新mysql后获取影响的行数发生异常解决方法
2013/03/28 PHP
php中把美国时间转为北京时间的自定义函数分享
2014/07/28 PHP
php判断两个浮点数是否相等的方法
2015/03/14 PHP
PHP中的魔术方法总结和使用实例
2015/05/11 PHP
注释PHP和html混合代码的小技巧(分享)
2016/11/03 PHP
javascript静态的url如何传递
2007/05/03 Javascript
兼容IE和FF的js脚本代码小结(比较常用)
2010/12/06 Javascript
js substr、substring和slice使用说明小记
2011/09/15 Javascript
jquery操作下拉列表、文本框、复选框、单选框集合(收藏)
2014/01/08 Javascript
JS获取节点的兄弟,父级,子级元素的方法
2014/01/09 Javascript
node.js中的path.delimiter方法使用说明
2014/12/09 Javascript
jQuery中element选择器用法实例
2014/12/29 Javascript
基于jQuery实现自动轮播旋转木马特效
2015/11/02 Javascript
百度地图给map添加右键菜单(判断是否为marker)
2016/03/04 Javascript
详解React-Todos入门例子
2016/11/08 Javascript
简单实现bootstrap导航效果
2017/02/07 Javascript
AngularJs定时器$interval 和 $timeout详解
2017/05/25 Javascript
vue2单元测试环境搭建
2018/05/24 Javascript
vue 表单输入格式化中文输入法异常问题
2018/05/30 Javascript
Vue中的v-for指令不起效果的解决方法
2018/09/27 Javascript
微信小程序购物车、父子组件传值及calc的注意事项总结
2018/11/14 Javascript
浅析Angular 实现一个repeat指令的方法
2019/07/21 Javascript
Vue简单封装axios之解决post请求后端接收不到参数问题
2020/02/16 Javascript
Python进程间通信用法实例
2015/06/04 Python
python可视化爬虫界面之天气查询
2019/07/03 Python
python用pip install时安装失败的一系列问题及解决方法
2020/02/24 Python
python读取hdfs并返回dataframe教程
2020/06/05 Python
python的flask框架难学吗
2020/07/31 Python
CSS3 优势以及网页设计师如何使用CSS3技术
2009/07/29 HTML / CSS
师范应届生教师求职信
2013/11/05 职场文书
幼儿园中班教师寄语
2014/04/03 职场文书
2015年项目工作总结
2015/04/29 职场文书
军训通讯稿范文
2015/07/18 职场文书
公开致歉信
2019/06/24 职场文书
利用python实时刷新基金估值(摸鱼小工具)
2021/09/15 Python
js 实现验证码输入框示例详解
2022/09/23 Javascript