scrapy要点复习与常用框架复习

Scrapy工作流程与注意点

  1. 从spiders抓取请求requests经过爬虫中间件发送给引擎
  2. 引擎将请求发送给调度器,调度器对请求进行调度
  3. 调度器将调度排序好的请求发送给引擎(调度器维护的是一个LIFO的队列,广度优先)
  4. 引擎将请求经过下载中间件发送给下载器
  5. 下载器将请求返回的response经过下载中间件发送给引擎
  6. 引擎将下载器返回的response返回给爬虫中间件
  7. 爬虫中间件将解析的字段与request返回给引擎
  8. 引擎将解析的字段发送给项目管道,将新的request发送给调度器
  • 注意点
  • 第四点是我们能应对反爬的最后一步,换代理,加cookie,换ua等等
  • 第五点最好是能在这里校验数据,不是正确的数据不传给spider


Scrapy的基本方法

基本流程:

  • 命令行
    1
    2
    3
    scrapy startproject projectname
    scrapy genspider spidername hostname
    scrapy crawl spidername

这里注意爬虫名称不要和项目名称相同

  • 最简化的scrapy爬虫的执行流程
  1. scrapy的name是用来标识是哪个爬虫的
  2. 不重写start_requests(),默认scrapy调用的是start_requests()获取start_url中的url
  3. 在执行第二步就默认回调parse()默认解析器

item主要函数

  1. process_item(self,item,spider)必须实现的函数,用来处理item,常用的就是处理items,需要这个item就返回,不需要就Dropitem
  2. open_spider(self,spider)不是必须实现的函数,当爬虫运行的时候调用
  3. close_spider(self,spider)不是必须实现的函数,当爬虫结束的时候调用
  4. from_crawler(cls,crawler)不是必须实现的函数,当爬虫运行时调用,比open_spider()还早,常用于初始化爬虫的一些属性。
  • 注意
  • yield管道里的时候就是yield item
  • yield调度器里就是yield requests

中间件

中间件最重要的作用就是拦截

下载中间件三大函数
  1. process_request(request,spider)处理拦截
  2. process_response(request,response,spider)处理拦截
  3. process_exception(request,exception,spider)常用来处理process_request的异常
process_request
  • 返回None,默认返回这个值,表示当前这层的下载中间件过了,去往下一层的下载中间件
  • 返回request,返回这个值就是把当前请求重新丢回调度器队列,相当于重试
  • 返回response,直接伪造一个返回值,把这个值丢到爬虫中解析
  • raises IgnoreRequest,抛弃当前的请求
process_response
  • 返回response,默认返回到了下载中间件当中。
  • 返回request,返回到队列当中,重新请求
  • 返回raises IgnoreRequest,忽略了之前的请求也要忽略它对应的response
process_exception
  • 返回None,就是不处理传给下一个中间件
  • 返回response,错误被纠正了,进入正常的流程
  • 返回request,返回给队列重新请求
CookieMiddleware
  • 单spider多cookie session

    1
    2
    for i,url in enumerate(url):
    yield scrapy.Request("xxxx.com",meta={'cookiejar':i},callback=self.parse_page)
  • 注意
    需要注意的是 cookiejar meta key 不是“黏性的”,需要再之后的request请求中接着传递

    1
    2
    3
    def parse_page(self,response):
    # do some processing
    return scrapy.Request("xxxx.com",meta={'cookiejar':response.meta['cookiejar']},callback=self.parse_other_page)
注意事项
  • 中间件后面的数字越小越远离下载器,数字越大越靠近下载器
  • 数字越小的request越先通过,数字越大的response越先通过
  • 这里比较重要的是retry模块还有CookieMiddleware模块
爬虫中间件
爬虫中间件的函数
  1. from_crawler
  2. process_spider_input
  3. process_spider_output
  4. process_spider_exception
  5. process_start_request
from_crawler(必须的)

会被manager调用

process_start_request

和process_spider_output很像,只能返回request

scrapy middleware的实例DepthMiddleware

scrapy的数据收集

收集404的页面demo
1
2
3
4
5
6
7
8
handle_httpstatus_list = [404]
def __init__(self):
self.fail_urls = []

def parse(self, response):
if response.status == 404:
self.fail_urls.append(response.url)
self.crawler.stats.inc_value("failed_url")

Request和Response

Reuqests对象

基础参数:

  • url 请求的网址
  • meta 用来在页面之间传递的参数
  • callback 请求回来的response处理函数
  • header 设置页面的请求头
  • cookie 请求页面cookie

高级参数:

  • encoding 请求的转换编码
  • priority 链接优先级
  • dont_filter 强制不过滤
  • errback 和callback一对,当请求成功时调用callback,请求失败调用errback

方法:

  • copy() 复制一个一模一样的对象,常用是deepcopy()
  • replace() 对对象参数进行替换

meta中常用的key:

Response对象

基础参数:

  • url 请求的url
  • body 请求回来的html
  • meta 用来在页面之间传递数据
  • headers 页面的headers数据
  • cookies 设置页面的cookie
  • Request 发出这个response对应的request对象

方法:

  • copy() 与request相同
  • replace() 与request相同
  • urljoin() 将页面的相对路劲传入,返回绝对路径
  • follow() 传入一个相对路径直接返回一个request对象

scrapy的暂停和重启

  • 暂停实例
    scrapy crawl spider lagou -s JOBDIR=job_info/001

spidername = lagou
workfilename = job_info
且每次请求都要求不一样的

  • 启动实例
    再次运行暂停的命令

自定义扩展

参考scrapy源码中的extensions这个包,可以查看corestats这个文件的源码

去重与入库

url去重
  • 用造好的轮子
  • scrapy-deltafetch(前两个原理相同)
  • scrapy-crawl-once
  • scrapy-redis
  • scrapy-redis-bloomfilters

  • 自己造轮子

  • 自己写的init_add_request方法实现轻量级的去重
scrapy_redis
  1. 运行爬虫:scrapy crawl 爬虫
  2. redis-cli lpush myspider:start_urls xxx.com
    redis-cli sadd myspider:start_urls xxx.com

SCHEDULR = “scrapy_rabbitmq_link.scheduler.SaaS”
RABBITMQ_CONNECTION_PARAMETERS=’amqp://guest:guest@localhost:5672/‘
SCHEDULR_REQUEUE_ON_STATUS=[500]
DOWNLOADER_MIDDLEWARES = {
‘scrapy_rabbitmq_link.middleware.RabbitMQMiddleware’:999
}

celery

from celery import Celery
app = Celery(‘hello’,broker=’amqp://guest@localhost//‘)
@app.task
def hello():
return ‘hello worlds’

编写代码中的小tip

  • 错误回调函数
1
2
3
4
from traceback import format_exc
def error_back(self,e):
_ = e
self.logger.error(format_exc())

通用爬虫-CrawlSpider

class scrapy.spiders.CrawlSpider
  • 爬取一般网站常用的spider
  • 定义一些规则来提供跟进link的方便机制
  • 导入scrapy.linkextractors import LinkExtractor
  • 每个link extractor 有唯一的公共方法是extract_links,他接收一个Response对象,返回scrapy.link.Link对象
常用参数

class scrapy.linkextractors.lxmlhtml.LxmlLinkExtractor()

  • allow() -正则
  • deny() - 正则
  • allow_domains() - 域名
  • deny_domains() - 域名
煌金 wechat
扫描关注公众号,回复「1024」获取为你准备的特别推送~
  • 本文作者: 煌金 | 微信公众号【咸鱼学Python】
  • 本文链接: http://www.xianyucoder.cn/2019/04/06/scrapy-intrduct/
  • 版权声明: 本博客所有文章除特别声明外,均采用 许可协议。转载请注明出处!
  • 并保留本声明和上方二维码。感谢您的阅读和支持!