scrapy 用爬虫规则指定爬行轨迹自动抓取

需求

  1. 给定爬虫起始地址,爬行路径,获得目标页的指定内容
  2. 约定路径 起点首页 --> (历史)频道 --> 小说info页–> 章节详情起始页 --> 作者中心 --> 大神之光
  3. 路径中的每个页面html结构都不同

分析

  1. 通用爬虫,写规则,用链接抽取器
  2. 为便于演示,只展示起点与终点页指定内容,中间路径以爬虫引擎debug信息展示

准备

  • scrapy 1.6
  • SelectorGadget 类似消消乐式浏览器扩展工具,点击消除颜色块,生成css或xapth表达式

代码

# -*- coding: utf-8 -*-
import scrapy
from scrapy.spiders.crawl import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

# item填充器
from scrapy.loader import ItemLoader
from scrapy.loader.processors import Join, MapCompose, TakeFirst

"""
爬虫深度测试
关注点在deep_max
"""


def q(url):
    print('提取的链接%s' % url)
    return url


def l(links):
    for link in links:
        print(link)
    return links


class QdSpider(CrawlSpider):
    name = 'qd'
    allowed_domains = ['qidian.com']
    start_urls = ['https://www.qidian.com/']

    rules = (
        Rule(
            LinkExtractor(
                # 允许爬虫深入的页面,每个响应页面只提取一个页面链接
                # 路径 历史频道 -> 选择特定的info ->章节->作者->大神之光 五个页面,至少5个深度
                allow=(r'(lishi)$', r'(info)\/(\d+)$', r'(chapter)/',
                       r'(authorIndex)', r'author/light/(\d+)$'),
                # 规则不通过,则会中断后续链接提取
                # deny=('chapter/(.*?)$',),
                # 从爬虫响应页面指定区域抽取,为便于观察每个页面只爬取一个链接
                restrict_css=(
                    # 首页响应提取历史链接
                    '.even:nth-child(8)',
                    # 历史频道响应页面info链接
                    '.sort-list h4 a',
                    # info页面提取免费试读(章节)链接
                    '#readBtn ',
                ),
                # 用xapth提取//协议开头的a 链接,restrict_css 不能提取诸如href="//me.qidian.com/..."这样的链接
                restrict_xpaths=(
                    # 章节页面提取作者家链接
                	'//h2//a',
                	# 提取作者页的大神之光链接
                	'//div[@class="author-sidebar-more"]/a[@class="blue"]'
                ),
                # process_value=q, 回调参数是提取的url字符串
            ),
            # 决定爬虫是否在符合规则的页面接着爬
            follow=True,
            # 可调用对象
            callback='parse_light',
            # 回调参数是个Link对象
            # process_links=l
        ),

    )

    def parse_start_url(self, response):
        # 起始地址解析,没有回调的scrapy蜘蛛(crawled)响应交给了parse方法
        yield {
            'nav_home': response.css('.nav-li a::text').extract(),
            'info': response.css('#notice h3 a::text').get()
        }

    def parse_light(self, response):
        # 每次 Crawled (200)地址都会被规则过一遍,通过者入此
        # self.log('[to...大神之光]%s...' % response.url)
      
        l_light = response.css('td:nth-child(1) .dark::text').extract()
        if len(l_light) > 0:
            return {
                'light': l_light
            }

执行

  • 在项目目录执行
scrapy crawl  qd

效果


2019-05-29 19:50:04 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.qidian.com/> (referer: None)
2019-05-29 19:50:04 [scrapy.core.scraper] DEBUG: Scraped from <200 https://www.qidian.com/>
{'nav_home': ['全部作品', '排行', '完本', '免费', '作家专区', '客户端'], 'info': '党员作家班结业'}
2019-05-29 19:50:04 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.qidian.com/lishi> (referer: https://www.qidian.com/)
2019-05-29 19:50:04 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://book.qidian.com/info/1012237441> (referer: https://www.qidian.com/)
2019-05-29 19:50:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://book.qidian.com/info/1011705052> (referer: https://www.qidian.com/lishi)
2019-05-29 19:50:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://read.qidian.com/chapter/M-D2AI2m8IBdi5-cWpsVtA2/eSlFKP1Chzg1> (referer: https://book.qidian.com/info/1012237441)
2019-05-29 19:50:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://read.qidian.com/chapter/rD2MpxrmEaLv7_WH3wfEdQ2/eSlFKP1Chzg1> (referer: https://book.qidian.com/info/1011705052)
2019-05-29 19:50:05 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://my.qidian.com/author/3228548> from <GET https://me.qidian.com/authorIndex.aspx?id=3228548>
2019-05-29 19:50:05 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://my.qidian.com/author/2438700> from <GET https://me.qidian.com/authorIndex.aspx?id=2438700>
2019-05-29 19:50:05 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://my.qidian.com/author/3228548> (referer: https://read.qidian.com/chapter/M-D2AI2m8IBdi5-cWpsVtA2/eSlFKP1Chzg1)
2019-05-29 19:50:06 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://my.qidian.com/author/2438700> (referer: https://read.qidian.com/chapter/rD2MpxrmEaLv7_WH3wfEdQ2/eSlFKP1Chzg1)
2019-05-29 19:50:06 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://my.qidian.com/author/light/3228548> (referer: https://my.qidian.com/author/3228548)
2019-05-29 19:50:06 [scrapy.core.scraper] DEBUG: Scraped from <200 https://my.qidian.com/author/light/3228548>
{'light': ['秋風夜影', 'milanmack', '谜月', '猿人阿兴', '猿人阿兴']}
2019-05-29 19:50:06 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://my.qidian.com/author/light/2438700> (referer: https://my.qidian.com/author/2438700)
2019-05-29 19:50:06 [scrapy.core.scraper] DEBUG: Scraped from <200 https://my.qidian.com/author/light/2438700>
{'light': ['秋風夜影', 'milanmack', '谜月', '猿人阿兴', '猿人阿兴']}
2019-05-29 19:50:06 [scrapy.core.engine] INFO: Closing spider (finished)

scrapy 通用爬虫

  • 流程
    • 一个不停从Scheduler中获取请求,发起,下载,处理,响应的过程
    • request --> download --> response
    • Spider <-- spider Middlewares --> Engine <-- Downloader Middlewares --> Downloader
    • Engine <---> Engine Scheduler
    • Engine -- processed items --> item Pipelines
  • 概念
    • Spider 页面解析回调 接收response对象,返回 items,requests,None,dict或baseRequest对象
    • 源请求地址不要在item填充阶段修改,所有对请求的修改放在中间件内进行
    • windows路径在linux下表示,要加盘符 如 'D:/code-base/python/crawl/bigPhoto'
    • scrapy.requset 对象发起的请求,未指定回调函数,则会进入蜘蛛的parse默认回调
    • Rule
      • Rule 对爬虫获取的响应页面进行链接分析
        • 若没有指定规则处理器(规则回调参数),则默认交给parse处理
        • 在debug中表现出来的就是对referer页的进行规则分析,若refer为None,则认为对downloader的start_url页面进行链接分析
      • follow布尔值 决定是否对符合规则的页面进一步爬取,即跟进链接分析
        • 通常规则参数没有回调,则为true, 默认为false
        • follow本质是否允许爬虫对规则回调的响应页面进行继续爬取
      • 规则回调生效条件
        • 提取的链接符合规则要求,包括链接处理,过滤
        • 需要爬虫爬过后的响应response,且该响应没有被禁止爬取,即follow为True
        • 使用规则的页面,是爬虫提请请求,由引擎调度下载器,下载器下完后返回的响应页面
          • 在debug看来,就是referer页
        • response.follow 会将response页作为referer页
      • 核心
        • 规则使用对象 对爬虫抓取页面 response响应 的分析处理
        • 是否对符合规则的页面进行链接分析(爬取),表现为Rule的follow参数,默认为false
        • 应用规则的爬虫响应页从哪来?
          • 起点start_url
          • 规则参数follow为True,所在的提取器得到的合规链接响应,(决定爬虫是否接着爬虫)
          • 表现: follow为True,所得到的链接会被所有规则作为响应源,作新一轮规则分析
        • 流程
          • 爬虫响应 --> 逐一应用规则 – 对follow=True所产生新的response->进行新一轮规则应用
          • 爬取 --> 响应 --> 规则分析 --> 处理器分发 --> 未指定则交给parse默认方法
        • 关键问题
          • 从哪儿爬? – 从爬虫响应页
          • 要不要继续爬? – follow参数
          • 最大deep_max问题 从起始页开始(不包含),起始->A页->B页 至少深度为2
      • 常见问题
        • 提取的链接有重定向,或重新拼接(通过js)成其它目标链接的痕迹,导致直接访问无响应,不能进行下一步follow处理
        • scrapy的css选择器不支持//开发的链接提取,建议链接提取器使用a标签
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值