利用scrapy爬取整站小说

2021-09-24 11:20:11 浏览数 (1)

利用scrapy爬取整站小说

今天带大家实践一把爬取整站小说,当然只是出于学习目的,大家千万不要应用于商业应用,因为可能出现侵权问题。本教程默认大家已经安装了scrapy,并且熟悉python语法。我们将逐步解析网站,然后将小说爬取保存到本地。

1.分析网页

通过点击查看各个网页的目录结构发现,小说的各个类目的网页结构都是一致的,所以我们只要能解析一个类目,那么基本所有的类目都可以解析,那么我们就暂时解析玄幻类目,解析完毕后,将其他类目加入爬取队列即可全站爬取。那么我们接下来就开始爬取

2.创建项目

使用scrapy命令创建项目,创建项目需要两条命令:

代码语言:javascript复制
//创建项目,最后一个参数为项目名称
>> scrapy startproject xiaoshuoSpider
//创建网站爬虫,参数分别为爬虫名称,爬取的目标网址
>>scrapy genspider biqugeu 'https://www.biqugeu.net/'

这样我们就创建成功了一个项目,项目的目录结构如下:

爬虫的初始化代码为:

start_urls就是我们要爬取的链接,大家可以看到这是一个列表,所以我们可以放多个链接,所以,我们用分类目录替换掉现在这个链接,

代码语言:javascript复制
start_urls = ["https://www.biqugeu.net/xuanhuanxiaoshuo/"]

然后接下来解析页面,打开f12开发者工具,如下图所示,我们可以清晰的看到目录结构,然后我们发现小说都是存在在li中,所以接下来我们只需要解析这个li标签就可以了,接下来我们写解析代码:

代码语言:javascript复制
    def parse(self, response):
    #解析a标签,得到小说名和详情章节目录页面地址
        booklist=response.xpath('//ul/li/span[@class="s2"]/a')
        #循环爬取到的小说,将其章节目录页的链接存放入scrapy的爬取队列
        for i in booklist:
            #章节目录页的url链接,
            href="https://www.biqugeu.net/" i.xpath("./@href").extract_first()
            #小说名称
            book_name=i.xpath("string(.)").extract_first()
             request= scrapy.Request(href,callback=self.parse_detail,dont_filter=True)
            #将书名传递给下一个解析函数
            request.meta["book_name"]=book_name
            yield request

接下来解析章节目录页面

同样打开f12,观察目录结构,我们发现所有的章节信息都在list这个div里面,每一个dd就是一个章节,但是开头有最新章节与正文中的章节肯定是重复的部分,所以如果全部解析的话,那么肯定会出现重复的部分,可能需要通过去重去处理,但是我的本意是将小说保存到本地,保存的目录结构应该为一个小说一个文件夹,每一章都是一个文件名,基于文件名的唯一性,有重复的小说进来,会覆盖写入,所以这里不会出现重复问题。

但是,假如是存储于数据库,是需要做重复性校验的。

代码语言:javascript复制
    def parse_detail(self,response):
        #解析章节目录列表
        chapterList=response.xpath('//div[@id="list"]/dl/dd/a')
        #循环获取章节目录信息
        for i in chapterList:
            href="https://www.biqugeu.net" i.xpath("./@href").extract_first()
            chapter_name=i.xpath("string(.)").extract_first()
            # 向下解析详情页
            request = scrapy.Request(href, callback=self.parse_content, dont_filter=True)
            request.meta["book_name"]=response.meta["book_name"]
            request.meta["chapter_name"]=chapter_name
            yield request

通过观察详情页信息,会发现,文章的正文都在content中,那么我们只需要把content中的文本信息解析出来即可,

代码语言:javascript复制
    def parse_content(self,response):
        #此处需要使用extract().是因为本身xpath解析出来是一个列表,我们需要把列表中的所有数据取出来
        content=response.xpath('//div[@id="content"]').xpath("string(.)").extract()
        # 将list以换行符分割,转换成字符串
        content="n".join(content)
        # 将结果存入item,传到pipline里进行存储
        item=XiaoshuospiderItem()
        item["content"]=content
        item["book_name"]=response.meta["book_name"]
        item["chapter_name"]=response.meta['chapter_name']
        yield item

将数据保存到本地

代码语言:javascript复制
import os
class XiaoshuospiderPipeline:
    def __init__(self):
        self.result="result/"
    def process_item(self, item, spider):
        # 获取传递过来的数据
        book_name=item["book_name"]
        chapter_name=item["chapter_name"]
        content=item["content"]
        # 判断文件夹是否已经创建
        if not os.path.exists(self.result book_name):
            os.makedirs(self.result book_name)
        # 判断章节是否已经爬取,未爬取,则写入
        if not os.path.exists(self.result book_name "/" chapter_name):
            with open(self.result book_name "/" chapter_name,"w") as f:
                f.write(content)
        return item

然后利用scrapy命令启动

代码语言:javascript复制
scrapy crawl biqugeu

然后我们会发现小说已经爬取下来了,结果如下图:

想要获取源码,关注微信公众号:会呼吸的Coder,回复:6893

0 人点赞