Scrapy--CrawlSpider 雨点打透心脏的1/2处 2022-02-13 15:43 245阅读 0赞 **目录** CrawlSpider简介 rules parse\_start\_url(response) Rule(爬取规则) Link Extractors CrawlSpider实战 创建项目 定义Item 创建CrawlSpider 编写Pipeline 启动爬虫 -------------------- # CrawlSpider简介 # class scrapy.spiders.CrawlSpider CrawlSpider 是 Spider 的一个子类,不仅天生就继承了Spider的所有特性,还在Spider的基础上提供了一些扩展能力:允许用户定义一些规则(Rule)来跟进那些需要继续爬取的URL(链接)。 除了从Spider继承过来的属性外,CrawlSpider 还提供了一个新的属性: ## rules ## 一个包含一个(或多个) Rule 对象的集合(list)。 每个 Rule 对爬取网站的一类URL链接定义了特定表现。 如果多个Rule匹配了相同的链接,则根据他们在本属性中被定义的顺序,第一个会被使用。 CrawlSpider 也提供了一个可复写(overrideable)的方法: ## parse\_start\_url(response) ## 当start\_url的请求返回时,该方法被调用。 该方法分析最初的返回值并必须返回一个 Item 对象或者 一个 Request 对象或者 一个可迭代的包含二者对象。 ## Rule(爬取规则) ## class scrapy.spiders.Rule(link_extractor, callback=None, cb_kwargs=None, follow=None, process_links=None, process_request=None) scrapy.spiders.Rule各项参数: * link\_extractor 是一个 Link Extractor 对象,用于定义需要提取的链接。 * callback 是一个callable 或 string ( 该spider 中同名的函数将作为回调函数被调用)。 从link\_extractor中每获取到匹配的链接时将会调用该函数。该回调函数接受一个response作为其第一个参数, 并返回一个包含 Item 以及(或) Request 对象(或者这两者的子类)的列表(list)。 * cb\_kwargs 包含传递给回调函数的参数(keyword argument)的字典。 * follow 是一个布尔(boolean)值,指定了根据该规则从response提取的链接是否需要跟进。 如果 callback 为 None, follow 默认设置为 True ,否则默认为 False 。 * process\_links 是一个callable或string(该spider 中同名的函数将作为回调函数被调用)。 从link\_extractor 中获取到链接列表时将会调用该函数。该方法主要用来过滤。 * process\_request 是一个callable或string(该spider 中同名的函数将作为回调函数被调用)。 该规则提取到每个request时都会调用该函数。该函数必须返回一个request或者None。 (用来过滤request) 警告:当编写爬虫规则时,请避免使用 parse 作为回调函数。 由于 CrawlSpider 使用 parse 方法来实现其逻辑,如果 您覆盖了 parse 方法,crawl spider 将会运行失败。 ## Link Extractors ## class scrapy.linkextractors.LinkExtractor Link Extractors 用来从网页(scrapy.http.Response 对象)中抽取最终将会被follow 的链接。 Link Extractors常用参数: * allow 满足括号中“正则表达式”的URL会被提取,如果为空,则全部匹配 * deny 满足括号中“正则表达式”的URL一定不提取(优先级高于 allow ) * allow\_domains 会被提取的链接的 domains * deny\_domains 一定不会被提取链接的domains * restrict\_xpaths 使用 xpath表达式,和 allow 共同作用过滤链接,即 xpath 满足范围内的 URL 会被提取 Scrapy提供了 scrapy.linkextractors import LinkExtractor , 但你可以通过实现一个简单的接口创建自己定制的Link Extractor来满足需求。 每个link extractor有唯一的公共方法是 extract\_links ,它接收一个 Response 对象,并返回一个 scrapy.link.Link 对象。Link Extractors,要实例化一次并且 extract\_links 方法会根据不同的response调用多次提取链接。 # CrawlSpider实战 # 本文将以爬取起点中文网中所有的免费文章(标题、简介、作者、文章地址)为例对CrawlSpider的用法进行示例。 ## 创建项目 ## 打开一个 Windows命令行窗口,切换到你打算存储代码的目录中(本例中是 D:\\scrapy),运行下列命令: d:\scrapy>scrapy startproject qidian_crawl 执行完该命令后,将会创建包含下列内容的 qidian\_crawl 目录: ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70][] ## 定义Item ## 在 items.py 中定义所需爬取的文章字段(标题、简介、作者、文章地址)。 import scrapy class QidianCrawlItem(scrapy.Item): title = scrapy.Field() # 标题 intro = scrapy.Field() # 简介 author = scrapy.Field() # 作者 url = scrapy.Field() # 文章地址 ## 创建CrawlSpider ## CrawlSpider 的创建方法跟普通的Spider类似,在Windows命令行执行如下命令完成创建: d:\scrapy>cd qidian_crawl d:\scrapy\qidian_crawl>scrapy genspider -t crawl qidian qidian.com 执行完该命令后,将会在 qidian\_crawl 的 spiders 目录下生成一个 qidian.py 文件 : ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70 1][] 我们要在 qidian.py 文件中编写爬取网站的链接URL提取和处理规则。 # -*- coding: utf-8 -*- import scrapy from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule from qidian_crawl.items import QidianCrawlItem class QidianSpider(CrawlSpider): # 继承自 class CrawlSpider(Spider) name = 'qidian' # 爬虫名称,启动爬虫时使用:scrapy crawl <爬虫名称> allowed_domains = ['qidian.com'] # 允许爬取的范围 ''' 爬虫的起始地址,其响应可使用 parse_start_url(response) 进行专门处理。 ''' start_urls = [ 'https://www.qidian.com/free/all?orderId=&vip=hidden&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=1&page=1'] def start_requests(self): # 启动时设置 Cookies ,Spider 的特性 cookies = 'e1=%7B%22pid%22%3A%22qd_P_xiangqing%22%2C%22eid%22%3A%22%22%7D; e2=%7B%22pid%22%3A%22qd_P_xiangqing%22%2C%22eid%22%3A%22%22%2C%22l1%22%3A4%7D; _csrfToken=0oIxR8Di1jdqyiUCGJAhBLcm6a0kyMuvmrq0vyjI; newstatisticUUID=1556264399_358226677; e2=%7B%22pid%22%3A%22qd_P_free%22%2C%22eid%22%3A%22qd_C44%22%7D; e1=%7B%22pid%22%3A%22qd_P_limitfree%22%2C%22eid%22%3A%22qd_E01%22%2C%22l1%22%3A4%7D' cookies = {i.split('=')[0]: i.split('=')[1] for i in cookies.split('; ')} yield scrapy.Request(self.start_urls[0], cookies=cookies) ''' 链接URL的提取和处理规则 ''' rules = ( Rule(LinkExtractor(allow=r'//book.qidian.com/info/\d+'), callback='parse_item', follow=False), Rule(LinkExtractor( allow=r'//www\.qidian\.com/free/all\?orderId=&vip=hidden&style=1&pageSize=20&siteid=1&pubflag=0&hiddenField=1&page=\d+'), follow=True), ) def parse_item(self, response): # 回调函数 item = QidianCrawlItem() item['url'] = response.request._url item['title'] = response.xpath("//div[@class='book-info ']/h1/em/text()").extract_first() item['author'] = response.xpath("//div[@class='book-info ']/h1/span/a/text()").extract_first() item['intro'] = response.xpath("//div[@class='book-info ']//p[@class='intro']/text()").extract_first() yield item ## 编写Pipeline ## CrawlSpider中收集的Item将会被传递到Item Pipeline中再次进行处理,在这里我们将提取到的QidianCrawlItem数据保存到文件中。 # -*- coding: utf-8 -*- from qidian_crawl.items import QidianCrawlItem import json class QidianCrawlPipeline(object): def process_item(self, item, spider): if isinstance(item, QidianCrawlItem): # 仅处理 QidianCrawlItem ,其他Item不予处理,直接返回 # 将文章数据保存到文件 with open('qidian.txt', 'a', encoding='utf-8') as f: json.dump(dict(item), f, ensure_ascii=False, indent=2) return item 在settings.py 中激活 Pipeline,并设置好 User-Agent 。 # Configure item pipelines # See https://doc.scrapy.org/en/latest/topics/item-pipeline.html ITEM_PIPELINES = { 'qidian_crawl.pipelines.QidianCrawlPipeline': 300, } # Crawl responsibly by identifying yourself (and your website) on the user-agent USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36' # Obey robots.txt rules ROBOTSTXT_OBEY = False ## 启动爬虫 ## 至此示例项目就算配置完成了,在Windows命令行执行如下命令来启动爬虫: d:\scrapy\qidian_crawl>scrapy crawl qidian 待程序执行完成后,会在Scrapy项目的根目录下生成一个qidian.txt文本文件。 ![watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70 2][] qidian.txt 中的前两条帖子内容如下: ![20190428152310501.png][] [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70]: /images/20220213/298ceaf2c2254bdd8a18d26a19691a5a.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70 1]: /images/20220213/421863fb51194425a258cb9701edd9e1.png [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3BlbmdqdW5sZWU_size_16_color_FFFFFF_t_70 2]: /images/20220213/5d3ab999155545108f2421dc2f0912f8.png [20190428152310501.png]: /images/20220213/c1b5f11ca33e45669d05326245b8fac4.png
还没有评论,来说两句吧...