CrawlSpider 详解

 

From:https://blog.csdn.net/weixin_37947156/article/details/75604163

 

CrawlSpider是爬取那些具有一定规则网站的常用的爬虫,它基于Spider并有一些独特属性

  • rules: 是Rule对象的集合,用于匹配目标网站并排除干扰
  • parse_start_url: 用于爬取起始响应,必须要返回ItemRequest中的一个。

因为 rules 是 Rule 对象的集合,所以这里也要介绍一下 Rule。它有几个参数:link_extractorcallback=Nonecb_kwargs=Nonefollow=Noneprocess_links=Noneprocess_request=None
其中的 link_extractor 既可以自己定义,也可以使用已有 LinkExtractor 类,主要参数为:

  • allow:满足括号中“正则表达式”的值会被提取,如果为空,则全部匹配。
  • deny:与这个正则表达式(或正则表达式列表)不匹配的URL一定不提取。
  • allow_domains:会被提取的链接的domains。
  • deny_domains:一定不会被提取链接的domains。
  • restrict_xpaths:使用xpath表达式,和allow共同作用过滤链接。还有一个类似的restrict_css

下面是官方提供的例子,我将从源代码的角度开始解读一些常见问题:

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractorclass MySpider(CrawlSpider):name = 'example.com'allowed_domains = ['example.com']start_urls = ['http://www.example.com']rules = (# Extract links matching 'category.php' (but not matching 'subsection.php')# and follow links from them (since no callback means follow=True by default).Rule(LinkExtractor(allow=('category\.php', ), deny=('subsection\.php', ))),# Extract links matching 'item.php' and parse them with the spider's method parse_itemRule(LinkExtractor(allow=('item\.php', )), callback='parse_item'),)def parse_item(self, response):self.logger.info('Hi, this is an item page! %s', response.url)item = scrapy.Item()item['id'] = response.xpath('//td[@id="item_id"]/text()').re(r'ID: (\d+)')item['name'] = response.xpath('//td[@id="item_name"]/text()').extract()item['description'] = response.xpath('//td[@id="item_description"]/text()').extract()return item

 

 

问题:CrawlSpider如何工作的?

 

因为CrawlSpider继承了Spider,所以具有Spider的所有函数。
首先由start_requestsstart_urls中的每一个url发起请求(make_requests_from_url),这个请求会被parse接收。在Spider里面的parse需要我们定义,但CrawlSpider定义parse去解析响应(self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)
_parse_response根据有无 callback,follow 和 self.follow_links执行不同的操作

    def _parse_response(self, response, callback, cb_kwargs, follow=True):##如果传入了callback,使用这个callback解析页面并获取解析得到的reques或itemif callback:cb_res = callback(response, **cb_kwargs) or ()cb_res = self.process_results(response, cb_res)for requests_or_item in iterate_spider_output(cb_res):yield requests_or_item## 其次判断有无follow,用_requests_to_follow解析响应是否有符合要求的link。if follow and self._follow_links:for request_or_item in self._requests_to_follow(response):yield request_or_item

其中_requests_to_follow又会获取link_extractor(这个是我们传入的LinkExtractor)解析页面得到的link(link_extractor.extract_links(response)),对url进行加工(process_links,需要自定义),对符合的link发起Request。使用.process_request(需要自定义)处理响应。

 

 

问题:CrawlSpider如何获取rules?

 

CrawlSpider类会在__init__方法中调用_compile_rules方法,然后在其中浅拷贝rules中的各个Rule获取要用于回调(callback),要进行处理的链接(process_links)和要进行的处理请求(process_request)

    def _compile_rules(self):def get_method(method):if callable(method):return methodelif isinstance(method, six.string_types):return getattr(self, method, None)self._rules = [copy.copy(r) for r in self.rules]for rule in self._rules:rule.callback = get_method(rule.callback)rule.process_links = get_method(rule.process_links)rule.process_request = get_method(rule.process_request)

那么Rule是怎么样定义的呢?

    class Rule(object):def __init__(self, link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=identity):self.link_extractor = link_extractorself.callback = callbackself.cb_kwargs = cb_kwargs or {}self.process_links = process_linksself.process_request = process_requestif follow is None:self.follow = False if callback else Trueelse:self.follow = follow

因此LinkExtractor会传给link_extractor。

 

 

有callback的是由指定的函数处理,没有callback的是由哪个函数处理的?

 

由上面的讲解可以发现_parse_response会处理有callback的(响应)respons。
cb_res = callback(response, **cb_kwargs) or ()
_requests_to_follow会将self._response_downloaded传给callback用于对页面中匹配的url发起请求(request)。
r = Request(url=link.url, callback=self._response_downloaded)

 

 

如何在CrawlSpider进行模拟登陆

 

因为CrawlSpider和Spider一样,都要使用start_requests发起请求,用从Andrew_liu大神借鉴的代码说明如何模拟登陆:

##替换原来的start_requests,callback为
def start_requests(self):return [Request("http://www.zhihu.com/#signin", meta = {'cookiejar' : 1}, callback = self.post_login)]
def post_login(self, response):print 'Preparing login'#下面这句话用于抓取请求网页后返回网页中的_xsrf字段的文字, 用于成功提交表单xsrf = Selector(response).xpath('//input[@name="_xsrf"]/@value').extract()[0]print xsrf#FormRequeset.from_response是Scrapy提供的一个函数, 用于post表单#登陆成功后, 会调用after_login回调函数return [FormRequest.from_response(response,   #"http://www.zhihu.com/login",meta = {'cookiejar' : response.meta['cookiejar']},headers = self.headers,formdata = {'_xsrf': xsrf,'email': '1527927373@qq.com','password': '321324jia'},callback = self.after_login,dont_filter = True)]
#make_requests_from_url会调用parse,就可以与CrawlSpider的parse进行衔接了
def after_login(self, response) :for url in self.start_urls :yield self.make_requests_from_url(url)

理论说明如上。

 

Scrapy.spiders.CrawlSpider的源代码

"""
This modules implements the CrawlSpider which is the recommended spider to use
for scraping typical web sites that requires crawling pages.
See documentation in docs/topics/spiders.rst
"""import copy
import sixfrom scrapy.http import Request, HtmlResponse
from scrapy.utils.spider import iterate_spider_output
from scrapy.spiders import Spiderdef identity(x):return xclass Rule(object):def __init__(self, link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=identity):self.link_extractor = link_extractorself.callback = callbackself.cb_kwargs = cb_kwargs or {}self.process_links = process_linksself.process_request = process_requestif follow is None:self.follow = False if callback else Trueelse:self.follow = followclass CrawlSpider(Spider):rules = ()def __init__(self, *a, **kw):super(CrawlSpider, self).__init__(*a, **kw)self._compile_rules()def parse(self, response):return self._parse_response(response, self.parse_start_url, cb_kwargs={}, follow=True)def parse_start_url(self, response):return []def process_results(self, response, results):return resultsdef _requests_to_follow(self, response):if not isinstance(response, HtmlResponse):returnseen = set()for n, rule in enumerate(self._rules):links = [lnk for lnk in rule.link_extractor.extract_links(response)if lnk not in seen]if links and rule.process_links:links = rule.process_links(links)for link in links:seen.add(link)r = Request(url=link.url, callback=self._response_downloaded)r.meta.update(rule=n, link_text=link.text)yield rule.process_request(r)def _response_downloaded(self, response):rule = self._rules[response.meta['rule']]return self._parse_response(response, rule.callback, rule.cb_kwargs, rule.follow)def _parse_response(self, response, callback, cb_kwargs, follow=True):if callback:cb_res = callback(response, **cb_kwargs) or ()cb_res = self.process_results(response, cb_res)for requests_or_item in iterate_spider_output(cb_res):yield requests_or_itemif follow and self._follow_links:for request_or_item in self._requests_to_follow(response):yield request_or_itemdef _compile_rules(self):def get_method(method):if callable(method):return methodelif isinstance(method, six.string_types):return getattr(self, method, None)self._rules = [copy.copy(r) for r in self.rules]for rule in self._rules:rule.callback = get_method(rule.callback)rule.process_links = get_method(rule.process_links)rule.process_request = get_method(rule.process_request)@classmethoddef from_crawler(cls, crawler, *args, **kwargs):spider = super(CrawlSpider, cls).from_crawler(crawler, *args, **kwargs)spider._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)return spiderdef set_crawler(self, crawler):super(CrawlSpider, self).set_crawler(crawler)self._follow_links = crawler.settings.getbool('CRAWLSPIDER_FOLLOW_LINKS', True)

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/495905.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MFC中实现的画箭头算法 (Arrow in MFC)

在codeproject中寻找到一个这样的算法,在这里介绍一下 可以改变三角形大小,顶点角度,是否填充和填充颜色等 但是画出的箭头还是不够美观....呵呵,还好吧 其中填充是代表箭头内是否填充颜色 先来看声明和实现 //使用一个结构体来存储相关的信息//Defines the attributes of…

Java8 Stream详解~排序:sorted

sorted,中间操作。有两种排序: sorted():自然排序,流中元素需实现Comparable接口 sorted(Comparator com):Comparator排序器自定义排序 「案例:将员工按工资由高到低(工资一样则按年龄由大到小…

英国上议院AI报告:没中美有钱,但我可以主导道德游戏规则设定

来源:网络大数据随着全球各国政府纷纷计划推出 AI 驱动下的未来,英国正准备承担一些学术和道德上的责任。最近,英国上议院 (House of Lords) 发布了一份183页的 报告《AI in the UK: ready, willing and able?》(《人工智能在英国&#xff1…

Java8 Stream详解~ 提取/组合

流也可以进行合并、去重、限制、跳过等操作。 public class StreamTest {public static void main(String[] args) {String[] arr1 { "a", "b", "c", "d" };String[] arr2 { "d", "e", "f", "g&…

Scrapy 下载器 中间件(Downloader Middleware)

Scrapy 下载器中间件官方文档:https://scrapy-chs.readthedocs.io/zh_CN/1.0/topics/downloader-middleware.html 官方 英文 文档:http://doc.scrapy.org/en/latest/topics/downloader-middleware.html#topics-downloader-middleware Scrapy 扩展中间件…

15 个 JavaScript Web UI 库

转载http://news.csdn.net/a/20100519/218442.html 几乎所有的富 Web 应用都基于一个或多个 Web UI 库或框架,这些 UI 库与框架极大地简化了开发进程,并带来一致,可靠,以及高度交互性的用户界面。本文介绍了 15 个非常强大的 Java…

2018年技术展望--中文版

来源:199IT互联网数据中心每年,《埃森哲技术展望》报告融合顶尖技术研究团队、行业领袖以及全球数据调研结果,发布未来三年内或将对各行各业产生重大影响的技术趋势判断,作为企业布局新战略的指导。2018年的《埃森哲技术展望》报告…

CompletableFuture详解~创建实例

创建 CompletableFuture 对象实例我们可以使用如下几个方法&#xff1a; static CompletableFuture<U> completedFuture(U value)//使用forkjoin公共线程池 static CompletableFuture<Void> runAsync(Runnable runnable) static CompletableFuture<U> suppl…

彻底搞懂 Scrapy 的中间件

彻底搞懂Scrapy的中间件&#xff08;一&#xff09;&#xff1a;https://www.cnblogs.com/xieqiankun/p/know_middleware_of_scrapy_1.html 彻底搞懂Scrapy的中间件&#xff08;二&#xff09;&#xff1a;https://www.cnblogs.com/xieqiankun/p/know_middleware_of_scrapy_2.h…

华为:5G技术前景堪忧,运营商将很难从5G赚钱

来源&#xff1a;FT中文网、5G作者&#xff1a;卢卡斯、法尔兹丨英国《金融时报》。未来智能实验室是人工智能学家与科学院相关机构联合成立的人工智能&#xff0c;互联网和脑科学交叉研究机构。未来智能实验室的主要工作包括&#xff1a;建立AI智能系统智商评测体系&#xff0…

PostgreSQL最常见问题

PostgreSQL最常见问题 常见问题1.1)PostgreSQL 是什么&#xff1f;该怎么发音&#xff1f;1.2)PostgreSQL 的版权是什么&#xff1f;1.3)PostgreSQL 可以运行在哪些操作系统平台上&#xff1f;1.4)我从哪里能得到 PostgreSQL&#xff1f;1.5)我从哪里能得到对 PostgreSQL 的支…

解决log4j多个日志都写到一个文件

之前客户端程序由于Websockt包依赖的log4j&#xff0c;就用log4j写日志了&#xff0c;Web用的log4j2没毛病。用log4j的多个logger的日志都写到一个文件里了&#xff0c;查了很多资料都没解决。今天闲了解决一下。 最后好使的配置 # 设置日志根 log4j.rootLogger INFO,Except…

CompletableFuture详解~设置任务结果

CompletableFuture 提供以下方法&#xff0c;可以主动设置任务结果。 boolean complete(T value) boolean completeExceptionally(Throwable ex) 第一个方法&#xff0c;主动设置 CompletableFuture 任务执行结果&#xff0c;若返回 true&#xff0c;表示设置成功。如果返回 …

Scrapy 爬虫去重效率优化之 Bloom Filter的算法的对接

From&#xff1a;https://cloud.tencent.com/developer/article/1084962 Python分布式爬虫打造搜索引擎Scrapy精讲—将bloomfilter(布隆过滤器)集成到scrapy-redis中https://www.cnblogs.com/adc8868/p/7442306.html scrapy redis bloomfilter &#xff1a;https://github.co…

为什么 AI 工程师要懂一点架构?

作者 | 王咏刚&#xff08;公众号ID&#xff1a;ban-qing-ren&#xff09;AI 时代&#xff0c;我们总说做科研的 AI 科学家、研究员、算法工程师离产业应用太远&#xff0c;这其中的一个含义是说&#xff0c;搞机器学习算法的人&#xff0c;有时候会因为缺乏架构&#xff08;In…

深度优先搜索遍历与广度优先搜索遍历

深度优先遍历过程 1、图的遍历 和树的遍历类似&#xff0c;图的遍历也是从某个顶点出发&#xff0c;沿着某条搜索路径对图中每个顶点各做一次且仅做一次访问。它是许多图的算法的基础。 深度优先遍历和广度优先遍历是最为重要的两种遍历图的方法。它们对无向图和有…

CompletableFuture详解~CompletionStage

CompletableFuture 分别实现两个接口 Future与 CompletionStage。 Future 接口大家都比较熟悉&#xff0c;这里主要讲讲 CompletionStage。 CompletableFuture 大部分方法来自CompletionStage 接口&#xff0c;正是因为这个接口&#xff0c;CompletableFuture才有如此强大功能…

Python 异步 IO 、协程、asyncio、async/await、aiohttp

From &#xff1a;廖雪峰 异步IO &#xff1a;https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152 Python Async/Await入门指南 &#xff1a;https://zhuanlan.zhihu.com/p/27258289 Python 生成器 和 yield 关键字&#xff1a;https://blog.csdn.net/free…

智能语音简史:这场技术革命从哪开始?

来源&#xff1a;与非网1952年&#xff0c;贝尔实验室&#xff08;Bell Labs&#xff09;制造一台6英尺高自动数字识别机“Audrey”&#xff0c;它可以识别数字0&#xff5e;9的发音&#xff0c;且准确度高达90&#xff05;以上。并且它对熟人的精准度高&#xff0c;而对陌生人…

四角号码检字法及查字方法的简介

四角号码检字法 由王云五&#xff08;1888—1979&#xff09;发明&#xff0c;汉语词典常用检字方法之一&#xff0c;用最多5个阿拉伯数字来对汉字进行归类。四角号码检字法用数字0到 9表示一个汉 字 四角的十种笔形&#xff0c;有时在最后增加一位补码。   四角号码检字法歌…