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

news2024/11/16 0:58:23

目录

前言

目的

思路

代码实现

1. 从给定的URL中拿到所有章节的标题和子链接

2. 将标题和子链接形成一个字典,便于后续提取信息

3. 实现在单个章节详细页面提取所有文本信息

4. 保存到本地文件,在前面加上数字序号便于顺序保存

5. 在主函数中添加线程池,遍历字典输入标题和子链接开始多线程任务

完整源码

运行效果

总结


前言

本来是想实现抓取番茄小说的,但是它虽然免费,当我写完全部代码的时候才发现后面的部分只能下载APP看,真是坑人......还好我把函数都封装了,整体逻辑是不变的,最终选择了另一个免费小说网——笔趣阁作为案例。

老规矩,我还是把链接放在评论区,不然审核不过的

同时我也会把番茄小说的放到最后的完整代码部分供大家借鉴。


目的

给定小说URL,使用Xpath+线程池实现抓取任意完整小说,并分章节按顺序保存到本地txt文件。


思路

思路其实很清晰:

1. 从给定的URL中拿到所有章节的标题和子链接

2. 将标题和子链接形成一个字典,便于后续提取信息

3. 实现在单个章节详细页面提取所有文本信息

4. 保存到本地文件,在前面加上数字序号便于顺序保存

5. 在主函数中添加线程池,遍历字典输入标题和子链接开始多线程任务


代码实现

详细的过程我就不在这里赘述了,之前讲过类似的案例:用异步法获取完整的一部小说

XPath也讲过的:XPath解析入门        实战:XPath法抓取某网站外包信息

小白可以先看上面几篇再看下面的代码会好懂一些。

1. 从给定的URL中拿到所有章节的标题和子链接

def get_chapter():
    chap_cnt = 1
    chapter_dic = {}
    for i in range(1, 100):
        new_url = novel_url + f'index_{i}.html'
        resp = requests.get(new_url, headers=headers)
        resp.encoding = 'gbk'
        resp_parser = etree.HTML(resp.text)
        if not resp_parser.xpath('/html/body/div[4]/dl/dd'):
            break
        chaps = resp_parser.xpath('/html/body/div[4]/dl/dd')
        for chap in chaps:
            if not chap.xpath("./a/@href"):
                break
            url = novel_url + chap.xpath("./a/@href")[0]
            title = f'{chap_cnt}_' + chap.xpath("./a/text()")[0]
            print(title)       

2. 将标题和子链接形成一个字典,便于后续提取信息

            chapter_dic[title] = url
            chap_cnt += 1
    return chapter_dic

3. 实现在单个章节详细页面提取所有文本信息

def get_novel(title, url):
    resp = requests.get(url, headers=headers)
    resp.encoding = 'gbk'
    novel = etree.HTML(resp.text)
    title = title
    content = novel.xpath('//*[@id="content"]//text()')

4. 保存到本地文件,在前面加上数字序号便于顺序保存

    if not os.path.exists('./7_Free_Novel_Folder'):
        os.mkdir('./7_Free_Novel_Folder')
    with open(f'./7_Free_Novel_Folder/{title}.txt', mode='a', encoding='gbk') as f:
        for cont in content:
            cont = cont.replace('\xa0', ' ')
            f.write(cont + '\n')
    print(title + '\t下载完成!')

5. 在主函数中添加线程池,遍历字典输入标题和子链接开始多线程任务

def main():
    chapter_dic = get_chapter()
    # 创建线程池
    with ThreadPoolExecutor(50) as t:
        for chapter in chapter_dic:
            t.submit(get_novel, title=chapter, url=chapter_dic[chapter])
    # 等待线程池中的任务全部执行完毕
    # get_novel('1', 'https://www.bbiquge.net/book/132573/55226877.html')
    print("Clear!!!")


if __name__ == '__main__':
    main()

完整源码

import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor
import os

novel_url = '见评论区'
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61'
}


def get_chapter():
    chap_cnt = 1
    chapter_dic = {}
    for i in range(1, 100):
        new_url = novel_url + f'index_{i}.html'
        resp = requests.get(new_url, headers=headers)
        resp.encoding = 'gbk'
        resp_parser = etree.HTML(resp.text)
        if not resp_parser.xpath('/html/body/div[4]/dl/dd'):
            break
        chaps = resp_parser.xpath('/html/body/div[4]/dl/dd')
        for chap in chaps:
            if not chap.xpath("./a/@href"):
                break
            url = novel_url + chap.xpath("./a/@href")[0]
            title = f'{chap_cnt}_' + chap.xpath("./a/text()")[0]
            print(title)
            chapter_dic[title] = url
            chap_cnt += 1
    return chapter_dic


def get_novel(title, url):
    resp = requests.get(url, headers=headers)
    resp.encoding = 'gbk'
    novel = etree.HTML(resp.text)
    title = title
    content = novel.xpath('//*[@id="content"]//text()')
    if not os.path.exists('./7_Free_Novel_Folder'):
        os.mkdir('./7_Free_Novel_Folder')
    with open(f'./7_Free_Novel_Folder/{title}.txt', mode='a', encoding='gbk') as f:
        for cont in content:
            cont = cont.replace('\xa0', ' ')
            f.write(cont + '\n')
    print(title + '\t下载完成!')


def main():
    chapter_dic = get_chapter()
    # 创建线程池
    with ThreadPoolExecutor(50) as t:
        for chapter in chapter_dic:
            t.submit(get_novel, title=chapter, url=chapter_dic[chapter])
    # 等待线程池中的任务全部执行完毕
    # get_novel('1', 'https://www.bbiquge.net/book/132573/55226877.html')
    print("Clear!!!")


if __name__ == '__main__':
    main()

下面我把番茄小说的也放上来,整体逻辑真的是一模一样,所以同样也适用其他的小说网,都大同小异:

import requests
from lxml import etree
from concurrent.futures import ThreadPoolExecutor
import os

domain = '见评论区'
novel_url = '见评论区'
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.61'
}


def get_chapter():
    resp = requests.get(novel_url, headers=headers)
    resp_parser = etree.HTML(resp.text)
    modules = resp_parser.xpath('//div[@class="page-body"]/div[4]/div')
    chapter_dic = {}
    chap_cnt = 1
    for module in modules:
        chapters = module.xpath("./div[@class='chapter']/div")
        for chapter in chapters:
            url = domain + chapter.xpath("./a/@href")[0]
            title = f'{chap_cnt}_' + chapter.xpath("./a/text()")[0]
            chapter_dic[title] = url
            chap_cnt += 1
    return chapter_dic


def get_novel(title, url):
    resp = requests.get(url, headers=headers)
    novel = etree.HTML(resp.text)
    title = title
    content = novel.xpath('//div[@class="muye-reader-content noselect"]//text()')
    if not os.path.exists('./7_Tomato_Novel_Folder'):
        os.mkdir('./7_Tomato_Novel_Folder')
    with open(f'./7_Tomato_Novel_Folder/{title}.txt', mode='a') as f:
        for cont in content:
            f.write(cont + '\n')
    print(title + '\t下载完成!')


def main():
    chapter_dic = get_chapter()
    # 创建线程池
    with ThreadPoolExecutor(50) as t:
        for chapter in chapter_dic:
            t.submit(get_novel, title=chapter, url=chapter_dic[chapter])
    # 等待线程池中的任务全部执行完毕
    print("Clear!!!")


if __name__ == '__main__':
    main()

运行效果

 


总结

本节实现了给定小说URL,使用Xpath+线程池实现抓取任意完整小说,并分章节按顺序保存到本地txt文件的任务。

如果想把所有小说放在同一个txt文件中只需要略微修改,把所有文本写到一个文件中遍历就好,相信看这篇文章的小伙伴有这个能力。如果想实现这个功能但是不会的也可以私信我,我帮你写一份。

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

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

相关文章

STL使用方法(C++)

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

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

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

JAVA 同步锁

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

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

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

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

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

【数据结构与算法】LRU Cache

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

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

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

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

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

Oracle——分析函数

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

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

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

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

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

关于java中的BigInteger

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

HTB_Weak RSA

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

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

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

CSS图标与链接

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

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

// package.json {"less": "^4.1.3","vite": "^3.1.0", }参考: [less/sass]如何避免因公共模块导致生成重复css代码解决 Vue CSS 样式重复载入,为 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 全局后置守卫案例:加载滚动条8. 路由元信息9. 路由过渡动效10…

瞧不上alert 老古董?使用alert实现一个精美的弹窗

曾几何时alert陪伴了我很多歌日日夜夜,但现在人们越来越追求高端的技术,其实慢慢的我也都快淡忘了前端的世界里还有alert这么一个伟大的成员。 目录 一、为什么抛弃了alert? 1. 不同浏览器的表现 2. 第三方组件的使用 3. 代码意识的控制 二、用al…

2023年浏览器哪个好用速度快,看这一篇就够了

在网络覆盖的社会,不管走到哪里,都能上网浏览新闻、看热点资讯。浏览器是用户上网浏览的必要软件之一,它决定这用户浏览网页的速度和习惯。那么,2023年什么浏览器好用稳定速度快?目前优秀的浏览器有很多,但…

HDFS常用命令汇总

HDFS常用命令汇总一、前言信息二、帮助信息查看1、查看帮助信息2、帮助文档(附带命令的详细说明)三、常用命令1、创建目录2、查看目录下的内容3、上传文件4、上传并删除源文件5、查看文件内容6、查看文件开头内容7、查看文件末尾内容8、下载文件9、合并下…