Scrapy中的CrawlSpider学习【上篇】1.Cr

这是我参与8月更文挑战的第19天,活动详情查看:8月更文挑战

1.CrawlSpider

(1)这是个啥玩意?
创建的继承CrawlSpider类的爬虫文件

(1)我们通过爬取纵横小说的内容来深入了解一下这个新玩意!

1.规划我们的目标:

咱的目标:
分四步走:
第一步: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,发送请求获得响应,得到对应章节的章节内容:(章节内容)

第一步:book.zongheng.com/store/c0/c0…

在这里插入图片描述

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

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

第四步:book.zongheng.com/chapter/431…

在这里插入图片描述

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

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

①完成第一步:通过解析start_urls的响应,获取到所有书籍的URL(为了避免一次爬取数据过多被封,通过特殊处理限定只获取一本小说的URL)

首先,编写爬虫文件:

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


class Bh3Spider(CrawlSpider):
    name = 'bh3'
    allowed_domains = ['book.zongheng.com']
    start_urls = ['http://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框架定义的一个类,它定义如何从每个已爬网页面中提取链接。
        # 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'http://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 = 'bh3'
    allowed_domains = ['book.zongheng.com']
    start_urls = ['http://book.zongheng.com/store/c0/c0/b0/u1/p1/v0/s1/t0/u0/i1/ALL.html']

    rules = (
        # 源码:Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True)
        # 1.LinkExractor是scrapy框架定义的一个类,它定义如何从每个已爬网页面中提取链接。
        # 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'http://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'http://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("http://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)
复制代码

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