对于刚接触scrapy的同学来说, crawlspider中的rule是比较难理解的, 很可能驾驭不住. 而且笔者在YouTube中看到许多公开的演讲都都错用了follow这一选项, 所以今天就来仔细谈一谈.

首先我们看scrapy中的follow是如何实现的:

# 为了方便理解, 去除了不必要代码
def _requests_to_follow(self, response):
"""遍历rules, 使用rule提取response中的链接
每个rule中提取的链接都会被添加到集合中
相同的链接只会被提取一次, 也就是范围大的rule 会覆盖范围小的rule
使用提取到的链接发送请求, 得到response """
seen = set()
for n, rule in enumerate(self._rules):
links = [lnk for lnk in rule.link_extractor.extract_links(response)
if lnk not in seen]
for link in links:
seen.add(link)
r = Request(url=link.url, callback=self._response_downloaded)
yield r def _response_downloaded(self, response):
rule = self._rules[response.meta['rule']]
return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)

首先, 在我们的定义中rules是一系列Rule对象的集合, 示例如下:

rules = (
Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),
Rule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),
)

在源代码中, 我们可以看到:

  1. 遍历所有的Rule对象, 并使用其link_extractor属性提取链接
  2. 对于提取到的链接, 我们把它加入到一个集合中
  3. 使用链接发送一个请求, 并且callback的最终结果是self._parse_response

上述操作表明, 当我们follow一个链接时, 我们其实是用rules把这个链接返回的response再提取一遍.

  • 当我们需要对response进行进一步提取的时候我们才使用follow, 它会把response用rules过滤一遍, 产生新的response.

  • 当我们的response包含有我们需要的信息是, 直接用callback提取信息.

  • 不要滥用follow, 因为我们提取出来的链接都会被下载, 造成了不必要的请求.

其实源代码中还解释了文档中提到的关于rules顺序的问题:

Each Rule defines a certain behaviour for crawling the site. Rules objects are described below. If multiple rules match the same link, the first one will be used, according to the order they’re defined in this attribute.

多个Rule匹配同一个链接, 只有第一个Rule会被使用, 用源代码来解释就是我们匹配到了链接已经添加到set中去重了, 所以之后的匹配都无法添加. 所以我们在使用rules时, 如果两个Rule有交集, 要注意顺序.

别再滥用scrapy CrawlSpider中的follow=True的更多相关文章

  1. Scrapy框架中的CrawlSpider

    小思考:如果想要通过爬虫程序去爬取”糗百“全站数据新闻数据的话,有几种实现方法? 方法一:基于Scrapy框架中的Spider的递归爬取进行实现(Request模块递归回调parse方法). 方法二: ...

  2. scrapy CrawlSpider解析

    CrawlSpider继承自Spider, CrawlSpider主要用于有规则的url进行爬取. 先来说说它们的设计区别: SpiderSpider 类的设计原则是只爬取 start_urls 中的 ...

  3. scrapy -->CrawlSpider 介绍

    scrapy -->CrawlSpider 介绍 1.首先,通过crawl 模板新建爬虫: scrapy genspider -t crawl lagou www.lagou.com 创建出来的 ...

  4. Python+Scrapy+Crawlspider 爬取数据且存入MySQL数据库

    1.Scrapy使用流程 1-1.使用Terminal终端创建工程,输入指令:scrapy startproject ProName 1-2.进入工程目录:cd ProName 1-3.创建爬虫文件( ...

  5. 再谈SQL Server中日志的的作用

    简介     之前我已经写了一个关于SQL Server日志的简单系列文章.本篇文章会进一步挖掘日志背后的一些概念,原理以及作用.如果您没有看过我之前的文章,请参阅:     浅谈SQL Server ...

  6. 用python随机生成数据,再插入到postgresql中

    用python随机生成学生姓名,三科成绩和班级数据,再插入到postgresql中. 模块用psycopg2 random import random import psycopg2 fname=[' ...

  7. C++ Primer 学习笔记_43_STL实践与分析(17)--再谈迭代器【中】

    STL实践与分析 --再谈迭代器[中] 二.iostream迭代[续] 3.ostream_iterator对象和ostream_iterator对象的使用 能够使用ostream_iterator对 ...

  8. Python爬虫从入门到放弃(十五)之 Scrapy框架中Spiders用法

    Spider类定义了如何爬去某个网站,包括爬取的动作以及如何从网页内容中提取结构化的数据,总的来说spider就是定义爬取的动作以及分析某个网页 工作流程分析 以初始的URL初始化Request,并设 ...

  9. 一定要 先删除 sc表 中的 某元组 行,,, 再删除 course表中的 元组行

    一定要  先删除 sc表 中的  某元组   行,,, 再删除  course表中的  元组行 course表 SC表 删除  course表中的  元组行,,出现错误 sc    ---->参 ...

随机推荐

  1. abs项目 - 战线拉的太长

    abs项目 - 战线拉的太长 “从项目中来,到项目中去”. 坑是踩不完的,尽量做到不要踩重复的坑就好. 最近的这个项目,从2016的8月份左右开始立项,一直做到2017的2月份,还是有很多的问题在继续 ...

  2. BZOJ 2597 剪刀石头布(最小费用最大流)(WC2007)

    Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道 ...

  3. DFS——hdu1016Prime Ring Problem

    一.题目回顾 题目链接:Prime Ring Problem Problem Description A ring is compose of n circles as shown in diagra ...

  4. 最短路径——Floyd算法(含证明)

    通过dij,ford,spfa等算法可以快速的得到单源点的最短路径,如果想要得到图中任意两点之间的最短路径,当然可以选择做n遍的dij或是ford,但还有一个思维量较小的选择,就是floyd算法. 多 ...

  5. 详细介绍javascript中的几种for循环的区别

    偶然间见到了forEach循环,感觉很新奇,就研究了一下,顺带着把js中的几种for循环做了一个比较. 首先,简单说一下,js中一共大概有四种for循环:(1).那种简单常见的for循环:(2).fo ...

  6. Bootstrap中轮播图

    Bootstrap中轮播图插件叫作Carousel,为了清晰的表明每个标签在这里是什么意思,我把解释写在了下面的代码中. <!-- 以下容器就是整个轮播图组件的整体, 注意该盒子必须加上 cla ...

  7. 【bzoj4998】星球联盟 LCT+并查集

    题目描述 在遥远的S星系中一共有N个星球,编号为1…N.其中的一些星球决定组成联盟,以方便相互间的交流.但是,组成联盟的首要条件就是交通条件.初始时,在这N个星球间有M条太空隧道.每条太空隧道连接两个 ...

  8. [洛谷P2147][SDOI2008]洞穴勘测

    题目大意:有$n$个洞穴,$m$条指令,指令有三种 $Connect\;u\;v$:在$u,v$之间连一条边 $Destroy\;u\;v$:切断$u,v$之间的边 $Query\;u\;v$:询问$ ...

  9. [Leetcode] word break ii拆分词语

    Given a string s and a dictionary of words dict, add spaces in s to construct a sentence where each ...

  10. BZOJ3533 [Sdoi2014]向量集 【线段树 + 凸包 + 三分】

    题目链接 BZOJ3533 题解 我们设询问的向量为\((x_0,y_0)\),参与乘积的向量为\((x,y)\) 则有 \[ \begin{aligned} ans &= x_0x + y_ ...