Python爬虫之Scrapy框架系列(12)——实战ZH小说的爬取来深入学习CrawlSpider

news2024/12/28 8:29:37

目录:

  • 1. CrawlSpider的引入:
    • (1)首先:观察之前创建spider爬虫文件时
    • (2)然后:通过命令scrapy genspider获取帮助:
    • (3)最后:使用模板crawl创建一个爬虫文件:
  • 2.CrawlSpider的正式讲解
    • 2.1 我们通过爬取ZH小说来深入了解它!
      • 规划我们的目标:
    • 2.2 先获取目标URL第一页的书籍信息!!!
      • ①第一步:通过解析start_urls的响应,获取所有书籍URL
      • ②第二步:通过解析书籍URL获取到的响应,获取以下数据:
      • ③第三步:通过解析书籍URL获取的响应里解析得到的每个小说章节列表页的所有URL,并发送请求获得响应:
      • ④第四步:通过解析对应小说的章节列表页获取到的每一章节的URL,发送请求获得响应,得到对应章节的章节内容:

1. CrawlSpider的引入:

(1)首先:观察之前创建spider爬虫文件时

之前使用scrapy框架时,我们创建spider爬虫文件使用的都是默认的basic模板:
在这里插入图片描述
观察使用这个命令创建的spider爬虫文件,可知它继承的是scrapy.Spider类:

在这里插入图片描述

(2)然后:通过命令scrapy genspider获取帮助:

在这里插入图片描述
使用帮助里的命令scrapy genspider -l命令可查看可用的爬虫模板:

在这里插入图片描述

(3)最后:使用模板crawl创建一个爬虫文件:

在这里插入图片描述

观察创建的爬虫文件,可知,它继承的是CrawlSpider类(注意:CrawlSpider类又继承了Spider类!),这就是本篇文章介绍的玩意:

在这里插入图片描述

2.CrawlSpider的正式讲解

  • 这是个啥玩意?
    创建的继承CrawlSpider类的爬虫文件!

2.1 我们通过爬取ZH小说来深入了解它!

规划我们的目标:

目标分四步走:
  • 第一步:start_urls—>纵横小说首页中选择完本,免费,总点击!!!:(书籍列表URL)
  • 第二步:通过解析start_urls获得的响应,获取到书籍列表URL。并解析书籍列表URL的响应,获取到以下数据:
    id,catagory(分类),book_name,author,status,book_nums,description,c_time,book_url,catalog_url
  • 第三步:通过解析书籍列表URL的响应,获取到每个小说章节列表页的URL,并发送请求获得响应,得到对应小说的章节列表页,获取以下数据:
    章节列表(id) , title(章节名称) content(内容),ordernum(序号),c_time,chapter_url(章节url),catalog_url(目录url)
  • 第四步:通过解析对应小说的章节列表页获取到每一章节的URL,发送请求获得响应,得到对应章节的章节内容:
    (章节内容)

第一步:http://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html

在这里插入图片描述

第二步:http://book.zongheng.com/book/431658.html
在这里插入图片描述

第三步:http://book.zongheng.com/showchapter/431658.html
在这里插入图片描述

第四步:http://book.zongheng.com/chapter/431658/7255260.html

在这里插入图片描述

一步步实现:贪多嚼不烂。按步骤来,一步一个脚印,分阶段获取所需内容,报错易查!!!

2.2 先获取目标URL第一页的书籍信息!!!

项目创建:

# 创建scrapy项目:
scrapy startproject zongheng

# 爬虫文件创建:
scrapy genspider -t crawl zh http://book.zongheng.com/

①第一步:通过解析start_urls的响应,获取所有书籍URL

  • (为了避免一次爬取数据过多被封,通过特殊处理限定只获取一本小说的URL)

首先,编写爬虫文件:

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


class Bh3Spider(CrawlSpider):
    name = 'zh'
    allowed_domains = ['book.zongheng.com']
    start_urls = ['https://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html']

    rules = (
        # Rule定义爬取规则: 1.提取url(LinkExtractor对象)   2.形成请求    3.响应的处理规则
        # 源码:Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)
        # 1.LinkExractor是scrapy框架定义的一个类,它定义如何从每个已爬网页面中提取url链接,并将这些url作为新的请求发送给引擎
        # 引擎经过一系列操作后将response给到callback所指的回调函数。
        # allow=r'Items/'的意思是提取链接的正则表达式   【相当于findall(r'Items/',response.text)】

        # 2.callback='parse_item'是指定回调函数。

        # 3.follow=True的作用:LinkExtractor提取到的url所生成的response在给callback的同时,还要交给rules匹配所有的Rule规则(有几条遵循几条)
        # 拿到了书籍的url                                  回调函数                            process_links用于处理LinkExtractor匹配到的链接的回调函数
        # 匹配每个书籍的url
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/book/\d+.html',
                           restrict_xpaths=("//div[@class='bookname']")), callback='parse_book', follow=True,
             process_links="process_booklink"),
    )

    def process_booklink(self, links):
        for index, link in enumerate(links):
            # 限制一本书
            if index == 0:
                print("限制一本书:", link.url)
                yield link
            else:
                return

    def parse_book(self, response):
        item = {}
        # item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
        # item['name'] = response.xpath('//div[@id="name"]').get()
        # item['description'] = response.xpath('//div[@id="description"]').get()
        return item

然后,配置settings.py里的必要配置后运行,即可发现指定页面第一本小说URL获取正常:
在这里插入图片描述

②第二步:通过解析书籍URL获取到的响应,获取以下数据:

  • id,catagory(分类),book_name,author,status,book_nums,description,c_time,book_url,catalog_url

首先,编写爬虫文件中callback指定的回调函数parse_book:

    def parse_book(self, response):
        print("解析book_url")
        # 字数:
        book_nums=response.xpath('//div[@class="nums"]/span/i/text()').extract()[0]
        # 书名:
        book_name=response.xpath('//div[@class="book-name"]/text()').extract()[0].strip()
        category=response.xpath('//div[@class="book-label"]/a/text()').extract()[1]
        author=response.xpath('//div[@class="au-name"]/a/text()').extract()[0]
        status=response.xpath('//div[@class="book-label"]/a/text()').extract()[0]
        description="".join(response.xpath('//div[@class="book-dec Jbook-dec hide"]/p/text()').extract())
        c_time=datetime.datetime.now()
        book_url=response.url
        catalog_url=response.css("a").re("http://book.zongheng.com/showchapter/\d+.html")[0]
        print(book_nums,book_name,category,author,status,description,c_time,book_url,catalog_url)

然后,运行可发现数据获取正常:

在这里插入图片描述

③第三步:通过解析书籍URL获取的响应里解析得到的每个小说章节列表页的所有URL,并发送请求获得响应:

  • 得到对应小说的章节列表页,获取以下数据:id , title(章节名称) content(内容),ordernum(序号),c_time,chapter_url(章节url),catalog_url(目录url)

首先:编写爬虫文件:(注意:1.这就需要我们再定义一个rules规则,进行书籍章节列表页的URL的获取以及对应响应数据的解析!2.编写相应的回调函数,进行书籍章节列表页信息的获取!)

# -*- coding: utf-8 -*-
import datetime

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class Bh3Spider(CrawlSpider):
    name = 'zh'
    allowed_domains = ['book.zongheng.com']
    start_urls = ['https://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html']

    rules = (
        # Rule定义爬取规则: 1.提取url(LinkExtractor对象)   2.形成请求    3.响应的处理规则
        # 源码:Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)
        # 1.LinkExractor是scrapy框架定义的一个类,它定义如何从每个已爬网页面中提取url链接,并将这些url作为新的请求发送给引擎
        # 引擎经过一系列操作后将response给到callback所指的回调函数。
        # allow=r'Items/'的意思是提取链接的正则表达式   【相当于findall(r'Items/',response.text)】

        # 2.callback='parse_item'是指定回调函数。

        # 3.follow=True的作用:LinkExtractor提取到的url所生成的response在给callback的同时,还要交给rules匹配所有的Rule规则(有几条遵循几条)
        # 拿到了书籍的url                                  回调函数                            process_links用于处理LinkExtractor匹配到的链接的回调函数
        # 匹配每个书籍的url
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/book/\d+.html',
                           restrict_xpaths=("//div[@class='bookname']")), callback='parse_book', follow=True,
             process_links="process_booklink"),

        # 匹配章节目录的url
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/showchapter/\d+.html',
                           restrict_xpaths=('//div[@class="fr link-group"]')), callback='parse_catalog', follow=True),
    )

    def process_booklink(self, links):
        for index, link in enumerate(links):
            # 限制一本书
            if index == 0:
                print("限制一本书:", link.url)
                yield link
            else:
                return

    def parse_book(self, response):
        print("解析book_url")
        # 字数:
        book_nums = response.xpath('//div[@class="nums"]/span/i/text()').extract()[0]
        # 书名:
        book_name = response.xpath('//div[@class="book-name"]/text()').extract()[0].strip()
        category = response.xpath('//div[@class="book-label"]/a/text()').extract()[1]
        author = response.xpath('//div[@class="au-name"]/a/text()').extract()[0]
        status = response.xpath('//div[@class="book-label"]/a/text()').extract()[0]
        description = "".join(response.xpath('//div[@class="book-dec Jbook-dec hide"]/p/text()').extract())
        c_time = datetime.datetime.now()
        book_url = response.url
        catalog_url = response.css("a").re("https://book.zongheng.com/showchapter/\d+.html")[0]
        print(book_nums, book_name, category, author, status, description, c_time, book_url, catalog_url)

    def parse_catalog(self, response):
        print("解析章节目录", response.url)  # response.url就是数据的来源的url
        # 注意:章节和章节的url要一一对应
        a_tags = response.xpath('//ul[@class="chapter-list clearfix"]/li/a')
        chapter_list = []
        for index, a in enumerate(a_tags):
            title = a.xpath("./text()").extract()[0]
            chapter_url = a.xpath("./@href").extract()[0]
            ordernum = index + 1
            c_time = datetime.datetime.now()
            catalog_url = response.url
            chapter_list.append([title, ordernum, c_time, chapter_url, catalog_url])
        print('章节目录:', chapter_list)

然后:运行会发现数据获取正常!
在这里插入图片描述

④第四步:通过解析对应小说的章节列表页获取到的每一章节的URL,发送请求获得响应,得到对应章节的章节内容:

  • (章节内容)

首先:编写爬虫文件:(注意:1.这就需要我们再定义一个rules规则,进行书籍具体章节内容的URL的获取以及对应响应数据的解析!2.编写相应的回调函数,进行书籍具体章节内容的获取!)

# -*- coding: utf-8 -*-
import datetime

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule


class Bh3Spider(CrawlSpider):
    name = 'zh'
    allowed_domains = ['book.zongheng.com']
    start_urls = ['https://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html']

    rules = (
        # Rule定义爬取规则: 1.提取url(LinkExtractor对象)   2.形成请求    3.响应的处理规则
        # 源码:Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)
        # 1.LinkExractor是scrapy框架定义的一个类,它定义如何从每个已爬网页面中提取url链接,并将这些url作为新的请求发送给引擎
        # 引擎经过一系列操作后将response给到callback所指的回调函数。
        # allow=r'Items/'的意思是提取链接的正则表达式   【相当于findall(r'Items/',response.text)】

        # 2.callback='parse_item'是指定回调函数。

        # 3.follow=True的作用:LinkExtractor提取到的url所生成的response在给callback的同时,还要交给rules匹配所有的Rule规则(有几条遵循几条)
        # 拿到了书籍的url                                  回调函数                            process_links用于处理LinkExtractor匹配到的链接的回调函数
        # 匹配每个书籍的url
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/book/\d+.html',
                           restrict_xpaths=("//div[@class='bookname']")), callback='parse_book', follow=True,
             process_links="process_booklink"),

        # 匹配章节目录的url
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/showchapter/\d+.html',
                           restrict_xpaths=('//div[@class="fr link-group"]')), callback='parse_catalog', follow=True),

        # 章节目录的url生成的response,再来进行具体章节内容的url的匹配     之后此url会形成response,交给callback函数
        Rule(LinkExtractor(allow=r'https://book.zongheng.com/chapter/\d+/\d+.html',
                           restrict_xpaths=('//ul[@class="chapter-list clearfix"]')), callback='get_content',
             follow=False, process_links="process_chapterlink"),
        # restrict_xpaths是LinkExtractor里的一个参数。作用:过滤(对前面allow匹配到的url进行区域限制),只允许此参数匹配的allow允许的url通过此规则!!!
    )

    def process_booklink(self, links):
        for index, link in enumerate(links):
            # 限制一本书
            if index == 0:
                print("限制一本书:", link.url)
                yield link
            else:
                return

    def process_chapterlink(self, links):
        for index,link in enumerate(links):
            #限制21章内容
            if index<=20:
                print("限制20章内容:",link.url)
                yield link
            else:
                return

    def parse_book(self, response):
        print("解析book_url")
        # 字数:
        book_nums = response.xpath('//div[@class="nums"]/span/i/text()').extract()[0]
        # 书名:
        book_name = response.xpath('//div[@class="book-name"]/text()').extract()[0].strip()
        category = response.xpath('//div[@class="book-label"]/a/text()').extract()[1]
        author = response.xpath('//div[@class="au-name"]/a/text()').extract()[0]
        status = response.xpath('//div[@class="book-label"]/a/text()').extract()[0]
        description = "".join(response.xpath('//div[@class="book-dec Jbook-dec hide"]/p/text()').extract())
        c_time = datetime.datetime.now()
        book_url = response.url
        catalog_url = response.css("a").re("https://book.zongheng.com/showchapter/\d+.html")[0]
        print(book_nums, book_name, category, author, status, description, c_time, book_url, catalog_url)

    def parse_catalog(self, response):
        print("解析章节目录", response.url)  # response.url就是数据的来源的url
        # 注意:章节和章节的url要一一对应
        a_tags = response.xpath('//ul[@class="chapter-list clearfix"]/li/a')
        chapter_list = []
        for index, a in enumerate(a_tags):
            title = a.xpath("./text()").extract()[0]
            chapter_url = a.xpath("./@href").extract()[0]
            ordernum = index + 1
            c_time = datetime.datetime.now()
            catalog_url = response.url
            chapter_list.append([title, ordernum, c_time, chapter_url, catalog_url])
        print('章节目录:', chapter_list)


    def get_content(self, response):
        content = "".join(response.xpath('//div[@class="content"]/p/text()').extract())
        chapter_url = response.url
        print('章节具体内容:',content)

然后:运行会发现数据获取正常!

在这里插入图片描述

在上面,我们实现了所有目标数据的获取,不过为了防封,所以限制为只获取第一本小说的信息!!!
需要注意的是:LinkExtractor中的restrict_xpaths参数,它的作用是:过滤(对前面allow匹配到的url进行区域限制),只允许此参数限制区域内的通过allow匹配的url通过!!!可以防止多个Rule规则都匹配到同一个URL,导致数据重复!!!

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

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

相关文章

从电影《流浪地球2》,看东西方价值观,中华文化五千年有原因的

说起今年的春节档电影&#xff0c;很多人都会想起《满江红》&#xff0c;因为这部由张艺谋导演的电影&#xff0c;票房一直在屡创新高。其实观众关注《满江红》的同时&#xff0c;也不要忘了另一部电影&#xff0c;贺岁片《流浪地球2》同样不可小觑。 一直以来&#xff0c;科幻…

【小程序】报错:no such file or directory, access ‘wxfile://usr/miniprogramLog/log2‘

出现场景 在微信小程序开发中&#xff0c;使用真机调试的时候&#xff0c;出现这个错误 解决方式 将真机调试由2.0切换到1.0

37. 实战:Xpath+线程池实现抓取任意完整小说一千余节到本地txt文件/模板任意小说网站可套用(附源码)

目录 前言 目的 思路 代码实现 1. 从给定的URL中拿到所有章节的标题和子链接 2. 将标题和子链接形成一个字典&#xff0c;便于后续提取信息 3. 实现在单个章节详细页面提取所有文本信息 4. 保存到本地文件&#xff0c;在前面加上数字序号便于顺序保存 5. 在主函数中添…

STL使用方法(C++)

目录 1 前言 2 迭代器 2.1 访问第一个元素 2.2 访问最后一个元素的下一个元素 2.3 遍历方法 2.3.1 while 2.3.2 for&#xff08;最常用&#xff09; 2.4 适用性 3 基本数据结构 3.1 vector&#xff08;动态数组&#xff09; 3.1.1 insert&#xff08;插入…

最全面的SpringBoot教程(一)——SpringBoot概述

前言 本文为 【SpringBoot教程】SpringBoot概述 相关知识&#xff0c;下边将对SpringBoot简介&#xff08;包括&#xff1a;什么是SpringBoot&#xff0c;SpringBoot的特点&#xff0c;SpringBoot的功能&#xff0c;SpringBoot官网&#xff09;&#xff0c;SpringBoot快速入门&…

JAVA 同步锁

文章目录synchronizedsynchronized 作用当前对象synchronized 作用订单号条件synchronized 作用订单号字符串条件ReentrantLock 加 ConcurrentHashMap需求&#xff1a; 同一个订单才加同步锁&#xff0c;不同订单可并行synchronized synchronized是Java中的关键字&#xff0c;…

python--飞机大战(课程设计)

实现功能&#xff1a; 1&#xff1a;飞机的移动&#xff0c;发射子弹&#xff0c;手雷&#xff0c;生命值&#xff0c;生命条 2&#xff1a;敌飞机有3种形态&#xff08;小&#xff0c;中&#xff0c;大&#xff09;不同的飞机大小不一样&#xff0c;生命值不一样&#xff0c…

【halcon学习-读图像和遍历文件下图像】

halcon学习-读图像和遍历文件下图像1.读取单张图像2.读取多张选定图片3.读取文件目录下所有的图片1.读取单张图像 与很多图像处理读图算子一样&#xff0c;halcon里读取单张图片的操作很简单&#xff1a; read_image(test1, D:/myfile/作业/拉链检测/chain1.bmp)也可以使用Ct…

【数据结构与算法】LRU Cache

&#x1f320;作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《数据结构与算法要啸着学》 &#x1f387;座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;…

2023年房地产融资模式研究报告

第一章 概况 融资&#xff0c;英文为 Financing&#xff0c;指为支付超过现金或转账的购货款而采取的货币交易手段&#xff0c;或者为取得特定资产而筹集资金所采取的货币手段。融资通常指货币资金的特有者和需求者之间&#xff0c;直接或间接地进行资金融通的活动。 广义的融…

【操作系统】多线程与多进程通信之深入理解【2023.01.31】

基本概念 首先&#xff0c;假设这么一个场景&#xff0c;进程A有线程Thread_A1和线程Thread_A2&#xff0c;进程B有线程Thread_B1和Thread_B2。举个例子&#xff0c;系统中进程的内存是独立的&#xff0c;也就是一台内存为4G的计算机&#xff0c;除了系统占用的1G部分&#xf…

Oracle——分析函数

文章目录前言介绍demo案例测试测试前的准备rank()dense_rank()row_number()前言 分析函数在oracle中比较常见&#xff0c;但用的不多&#xff0c;今天有幸碰见&#xff0c;索性做一次使用的总结说明。 介绍 oracle中的分析函数&#xff0c;常见的有下面的三种&#xff1a; r…

四季度亏损扩大,Meta Reality Labs近4年财报营收汇总

2月2日青亭网报道&#xff0c;Meta今天发布了2022财年第四季度财报、全年财报。根据22年四季度财报信息显示&#xff0c;Reality Labs业务部门营收营收7.27亿美元&#xff0c;同比&#xff08;21年四季度8.77亿美元&#xff09;要下降17.1%&#xff1b;净亏损42.79亿美元&#…

R语言多元数据统计分析在生态环境中的应用

生态环境领域研究中常常面对众多的不同类型的数据或变量&#xff0c;当要同时分析多个因变量&#xff08;y&#xff09;时需要用到多元统计分析&#xff08;multivariate statistical analysis&#xff09;。多元统计分析内容丰富&#xff0c;应用广泛&#xff0c;是非常重要和…

关于java中的BigInteger

文章目录关于BigInteger类BigInteger的构造方法BigInteger方法使用示例算术运算API转换为基本数据类型的方法小结关于BigInteger类 BigInteger类是用于解决整型类型&#xff08;含基本数据类型及对应的包装类&#xff09;无法表示特别大的数组及运算问题。 即使是占用字节数最…

HTB_Weak RSA

文章目录信息收集RSA 算法题目解密信息收集 下载&#xff0c;解压 (密码都是hackthebox) enc后缀的文件是一种加密文件&#xff0c;打开为乱码&#xff0c;key.pub内容如下&#xff0c;是 RSA 加密算法的公钥 -----BEGIN PUBLIC KEY----- MIIBHzANBgkqhkiG9w0BAQEFAAOCAQwAMI…

CISP信息安全认证考试都考什么?

CISP考试是目前热门的信息安全认证考试&#xff0c;很多刚刚开始了解CISP的朋友&#xff0c;比较关心关于CISP考试内容的相关问题&#xff0c;今天就由中培小编带大家一起去看看CISP认证考试究竟都考哪些内容&#xff1f;首先来看一下试卷结构考试时间&#xff1a;120分钟考试题…

CSS图标与链接

目录 如何添加图标 Font Awesome 图标 实例 Bootstrap 图标 实例 Google 图标 实例 为图标添加样式或颜色 设置链接样式 实例 实例 文本装饰 实例 背景色 实例 链接按钮 实例 更多实例 如何添加图标 向 HTML 页面添加图标的最简单方法是使用图标库&#xff0…

【Less】全局样式重复注入问题

// package.json {"less": "^4.1.3","vite": "^3.1.0", }参考&#xff1a; [less/sass]如何避免因公共模块导致生成重复css代码解决 Vue CSS 样式重复载入&#xff0c;为 Vue 添加全局 less 或 sass 基础样式库【不是本篇解决方法&am…

vue3学习笔记之router(router4 + ts)

文章目录Vue Router1. 基本使用router-view2. 路由跳转2.1 router-link2.2 编程式导航2.3 replace3. 路由传参4. 嵌套路由5. 命令视图6. 重定向和别名6.1 重定向6.2 别名7. 路由守卫7.1 全局前置守卫7.2 全局后置守卫案例&#xff1a;加载滚动条8. 路由元信息9. 路由过渡动效10…