干货|理解Python爬虫框架pyspider

Posted AI遇见机器学习

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了干货|理解Python爬虫框架pyspider相关的知识,希望对你有一定的参考价值。

原创干货,第一时间送达

一、pyspider简介


pyspider是Binux做的一个爬虫架构的开源化实现,主要功能有 :

  • 抓取、更新调度多站点的特定的页面

  • 需要对页面进行结构化信息提取

  • 灵活可扩展,稳定可监控

pyspider以去重调度,队列抓取,异常处理,监控等功能作为框架,只需提供给抓取脚本,并保证灵活性。最后加上web的编辑调试环境,以及web任务监控,即成为了这套框架。pyspider的设计基础是:以python脚本驱动的抓取环模型爬虫
干货|理解Python爬虫框架pyspider

  • 各个组件间使用消息队列连接,除了scheduler是单点的,fetcher 和 processor 都是可以多实例分布式部署的。 scheduler 负责整体的调度控制

  • 任务由 scheduler 发起调度,fetcher 抓取网页内容, processor 执行预先编写的python脚本,输出结果或产生新的提链任务(发往 scheduler),形成闭环

  • 每个脚本可以灵活使用各种python库对页面进行解析,使用框架API控制下一步抓取动作,通过设置回调控制解析动作


二、pyspider界面

在终端输入pyspider all 运行pyspider服务,然后再浏览器中输入 localhost:5000 即可看到pyspider的界面,rate 用于控制每秒抓取页面的个数,burst 可以视为并发控制。如果要删除项目则需要将group设置为delete,status设置为stop,24小时候项目就会删除。干货|理解Python爬虫框架pyspider

点击create可以创建项目
干货|理解Python爬虫框架pyspider
点击刚创建的项目打开脚本编辑界面
干货|理解Python爬虫框架pyspider
我们可以在这里编写并调试脚本,测试时web可以显示网页,web左边的按钮为css选择器,html为网页的源代码,follows显示可以爬取的url,具体的调试亲身体验过就知道了。

三、pyspider脚本

但你创建新的工程的时候你会看到这些默认的脚本模板,接下来为大家简单介绍pyspider脚本的编写。

from pyspider.libs.base_handler import *class Handler(BaseHandler):
   crawl_config = {
   }

   @every(minutes=24 * 60)    def on_start(self):
       self.crawl('__START_URL__', callback=self.index_page)

   @config(age=10 * 24 * 60 * 60)    def index_page(self, response):        for each in response.doc('a[href^="http"]').items():
           self.crawl(each.attr.href, callback=self.detail_page)

   @config(priority=2)    def detail_page(self, response):        return {            "url": response.url,            "title": response.doc('title').text(),
       }
  • crawl_config:爬虫的全局参数设置,例如请求头和cookies可以在这里设置(传入关键字及对应的参数即可)

  • on_start(self):爬虫开始爬取的入口

  • crawl:和requests有相同的功能 ,可以支持 get(默认) 和 post,常用的参数有

    • data 是想要提交数据

    • callback 可以在执行完 crawl后调用回调函数

    • method 是指定 访问方法

    • files 上传文件,{'key': ('file.name': 'content')}

    • headers  请求头,类型dict

    • cookies 请求的 Cookies 类型 dict

    • timeout  请求内容里最大等待秒数.默认值:120

    • connect_timeout : 指定请求时链接超时时间,单位秒,默认值:20

    • proxy : 可以设置代理服务器,暂时只支持http代理

更多参数使用可以查看官方文档。

  • response

    • crawl :返回的对象是 response 对象

    • response.text : 请求响应的文本格式内容**(如果Response.encoding 是 None 或 chardet 模块可用, 响应内容会自动被解析为指定的编码)**

    • response.doc : 本方法会调用PyQuery库用返回的内容生成一个PyQuery对象以方便使用,生成对象时默认已经把里面的所有链接格式化成绝对链接,可直接分析使用(具体使用对象方法可以参考PyQuery官方参考手册)

    • response.json : 本方法会调用JSON相关库来解析返回的内容

    • response.status_code : 返回响应的状态码

    • response.headers : 请求响应的头信息,dict格式

    • response.cookies : 响应的cookies

    • response.time : 抓取使用的时间

  • index_page和detail_page只是初始脚本中的回调函数,除了on_start,其他的函数名可以自定

  • @every(minutes=24 * 60) 设置多久执行一次(24*60为一天一次,因此可以每天都爬一次获取数据)

  • @config

    • age 设置任务的有效期限,在这个期限内目标爬取的网页被认为不会进行修改,以秒为单位

    • priority 设定任务优先级

    • auto\_recrawl  设置是否每到age时间重新爬取一次,默认值是:False

    • priority  这个参数用来指定任务的优先级,数值越大越先被执行,默认值为 0

    • retries  任务执行失败后重试次数,默认值是 3

    • itag  任务标记值,此标记会在抓取时对比,如果这个值发生改变,不管有效期有没有到都会重新抓取新内容.多数用来动态判断内容是否修改或强制重爬,默认值是 None


mac os 安装pyspider的坑(不是mac系统的朋友可以忽略)

mac系统下安装pyspider时你可能会遇到pycurl的导入错误


ImportError: pycurl: libcurl link-time ssl backend (openssl) is different from compile-time ssl backend (none/other)


这个问题可以通过重装pycurl解决,但是在高版本的mac系统中的系统环境变量是不存在openssl的头文件的。在终端输入以下指令则可以解决问题

pip uninstall pycurl# 卸载库
export PYCURL_SSL_LIBRARY=openssl
export LDFLAGS=-L/usr/local/opt/openssl/lib
export CPPFLAGS=-I/usr/local/opt/openssl/include# openssl相关头文件路径
pip install pycurl --compile --no-cache-dir# 重新编译安装

系统环境:Mac High Sierra 10.13.2

四、特殊技巧


模拟登录

有很多网站需要登录之后才能浏览更多的内容,因此我们的爬虫需要实现模拟登录的功能,我们可以通过 selenium 来实现模拟登录。

selenium 是一个用于Web应用程序测试的工具,同时我们也可以通过 selenium 实现登录功能。以微博为例

from selenium import webdriver
driver = webdriver.Chrome()
driver.get("https://weibo.com/")
username = driver.find_element_by_css_selector("input#loginname")
username.clear()
username.send_keys('your_username')
password = driver.find_element_by_css_selector('span.enter_psw')
password.clear()
password.send_keys('your_password')

在输入账号和密码后,最大的问题来了,验证码都是图片,一般我们要借助图像识别才能识别验证码,但是由于验证码的种类非常多(英文、数字、中文或者它们的混合),而且验证码还可能被一定的旋转、扭曲甚至互相粘连,以至于人眼也不能很好的辨认,因此大多数模型的通用性和准确率并不是很高。因此效率最高的方法就是在selenium打开浏览器之后手动登录(过程中调用time.sleep()暂停程序)。因为对于爬虫来说最重要的不是解决登录问题,因此这么做可以节约大量的时间以及代码量,虽然很蠢,但是很有用。

完成登录后,用一下代码即可获取cookie,并把cookie_dict传给pyspider全局参数中的cookies即可

cookies_dict = {}
cookies = driver.get_cookies()
for cookie in cookies:
  cookies_dict[cookie['name']] = cookie['value']
JS

普通的requests请求只能抓取静态HTML网页, 但是大部分网站都是混入了JS数据加载,数据是延迟加载的,想要抓取这些内容可以使用selenium + PhantomJS完全渲染网页后再进行网页解析。PhantomJS是一个无界面的,可脚本编程的WebKit浏览器引擎,使用方法和使用selenium + Chrome模拟登录是类似的,但由于PhantomJS没有界面因此内存消耗会少很多。

爬取AJAX异步加载网页

AJAX 是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新。爬取AJAX异步加载的网页我们要去分析网页的发出的请求以及返回的信息。具体的我们要使用Google浏览器的开发者工具(火狐还有其他浏览器也有这个)查看网络的XHR那里,但网页局部更新的时候,浏览器发出了什么请求,并且查看浏览器返回来什么。

在我们微博登录后的主页,只要把滚动条移动到最下面就会发现会刷出新的微博,这是我们打开开发者工具,不断的往下滚,然后你会发现但你刷出新的信息时总会发出一个新的请求,并且它返回的json中data为刷新微博的html。

干货|理解Python爬虫框架pyspider干货|理解Python爬虫框架pyspider

干货|理解Python爬虫框架pyspider

干货|理解Python爬虫框架pyspider

干货|理解Python爬虫框架pyspider

仔细观察发现其中pagebar这里的变化有规律,并且id减少了15对应了新刷出的15条微博。因此可以推测pagebar应该是刷出新微博的关键。在这之前我们要给爬虫加一个请求头部,否则很有可能被服务器识别为机器人而无法成功访问。请求头同样可以在开发者工具那里找到。

def on_start(self):        
   for i in range(10):
       url = 'https://weibo.com/aj/mblog/fsearch?pagebar=%s'%i
       self.crawl(url, callback=self.index_page)

发现成功爬取并返回了微博的内容。接下来只需对你所需要的信息进行处理即可。