Python制作读者下载器,实现随时随地免费看

news2024/11/17 15:53:06

前言

嗨喽,大家好呀~这里是爱看美女的茜茜呐

又到了学Python时刻~

一个看书党一年有多少money投入小说行业呢~

碰上一本好看的书,你能购买上多少章呢~

其中的投入,无法想象,尤其是兴致上来了,不得投上个礼物给作者催催更?

最近,我朋友发现了我有着个小说下载器,立马找上我

要我给她下上个几千张,可以随时观看,这样即省了钱,又看了小说

(当然,如果你手上还算富裕,可以支持作者正版小说哦~)

基本四个步骤:

采集一章小说内容

  1. 发送请求, 模拟浏览器对于url地址发送请求

  2. 获取数据, 获取网页源代码

  3. 解析数据, 提取我们想要的数据内容

    小说章节名

    小说内容

  4. 保存数据, 把小说内容本地文件 txt

代码展示

导入模块

# 导入数据请求模块
import requests
# 导入数据解析模块
import parsel
# 导入正则
import re
# 导入格式化打印
import prettytable as pt
# 导入进度条
from tqdm import tqdm

伪装

请求头 字典数据类型, 构建完整键值对

headers = {
    # user-agent 用户代理 表示浏览器基本身份信息
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.0.0 Safari/537.36'
}


def get_response(html_url):

发送请求

自定义函数:

  • def 关键字 定义函数

  • get_response 函数名 自定义

html_url 形式参数

  • :param html_url: 给个网址就可以了

  • :return:response 返回响应对象

模拟浏览器对于url地址发送请求

headers 请求头 --> 可以直接复制粘贴

    # 发送请求
    response = requests.get(url=html_url, headers=headers)
    return response

return 关键字 返回 response 响应对象

<Response [200]> 响应对象 表示请求成功

获取小说名字 / 小说章节url

def get_novel_info(novel_url):
    """
    获取小说名字 / 小说章节url
    :param novel_url: 小说目录页url地址
    :return:
    """
    # 发送请求, 获取网页源代码
    html_data = get_response(html_url=novel_url).text
    # 把获取下来 html字符串数据 <response.text>, 转成可解析对象
    selector = parsel.Selector(html_data)
    # 提取小说名字
    name = selector.css('.novel_info_title h1::text').get()
    # 提取小说章节url  attr 属性选择器, 提取标签里面属性内容
    link_list = selector.css('.chapter_list a::attr(href)').getall()
    # https://ssbiqu.com/book/5613/4217210.html  列表推导式
    link_list = ['https://****.com' + i for i in link_list]
    return name, link_list

获取小说内容函数

def get_content(html_url):
    """
    获取小说内容函数
    :param html_url: 形参 传入小说章节url地址
    :return: 章节名 / 小说内容
    """
    # 调用前面定义好的发送请求函数
    response = get_response(html_url=html_url)
    # 获取网页源代码, html字符串数据
    # print(response.text)

解析提取,

小说章节名, 以及小说内容

  • 根据标签属性提取数据内容

    1. 小说章节名字

      .style_h1 定位标签

      get() 获取第一个标签内容 相当于获取一个, 返回字符串

      getall() 获取所有标签内容, 返回列表

html字符串数据 <response.text>, 转成可解析对象

selector = parsel.Selector(response.text)

提取标题

title = selector.css('.style_h1::text').get()

提取内容

content_list = selector.css('#article>p::text').getall()

保存文字, 保存字符串数据

所有要把 列表转成字符串数据类型

列表转成字符串数据类型?

for 遍历提取列表里面元素

str 强制转换数据类型

str.join() 把列表合并为字符串

'\n'.join(content_list) 以换行符, 把列表里面元素一个一个合并起来变成一个字符串

content = '\n'.join(content_list)

返回标题, 小说内容

return title, content

保存函数

def save(name, title, content):
    """
    python学习交流Q裙:261823976 ### 源码领取
    保存函数
    :param title: 小说章节名
    :param content: 小说内容
    :return:
    """
    # # replace 字符串替换, 把 / 替换成 -
    # title = title.replace('/', '-')  保存 a 追加 w 写入会覆盖
    with open(name + '.txt', mode='a', encoding='utf-8') as f:
        f.write(title)
        f.write('\n')
        f.write(content)
        f.write('\n')

搜索函数

def search(word):
    """
    搜索函数
    :param word: 小说名
    :return:
    """
    search_url = 'https://*****.com/search/'
    data = {
        'searchkey': word
    }
    search_data = requests.post(url=search_url, data=data, headers=headers).text
    novel_id_list = re.findall('<a href="/book/(\d+)/">', search_data)
    name_list = re.findall('<h3>(.*?)<span class="hot">(.*?)</span>(.*?)</h3>', search_data)
    name_list = [''.join(j) for j in name_list]
    # 仅匹配中文
    writer_list = re.findall('<i class="fa fa-user-circle-o">&nbsp;</i>.*?(.*?)&nbsp;&nbsp;<span class="s_gray">', search_data)
    writer_list = [z.replace('<span class="hot">', '').replace('</span>', '') for z in writer_list]
    tb = pt.PrettyTable()
    tb.field_names = ['序号', '书名', '作者', '书ID']
    page = 0
    novel_info_list = []
    for novel_id, name, writer in zip(novel_id_list, name_list, writer_list):
        dit = {
            '书名': name,
            '作者': writer,
            '书ID': novel_id,
            '信息': '完整源码获取加Q裙: 261823976'
        }
        print(dit)
        novel_info_list.append(dit)
        tb.add_row([page, name, writer, novel_id])
        page += 1
    print(tb)
    num = input('请输入你想要下载小说序号: ')
    novel = novel_info_list[int(num)]['书ID']
    return novel

获取小说名字

ef main(word):
    """
    主函数
    :return:
    """
    novel_id = search(word)
    # 小说目录页 https://ssbiqu.com/book/5613/
    url = f'https://****.com/book/{novel_id}/'
    # 获取小说名字
    name, link_list = get_novel_info(novel_url=url)
    # for循环遍历 提取内容
    for link in tqdm(link_list):
        # 获取小说内容
        title, content = get_content(html_url=link)
        save(name, title, content)

PS:源码如有需要的小伙伴可以加下方的群去找管理员免费领取

尾语 💝

我给大家准备了一些资料,包括:

2022最新Python视频教程、Python电子书10个G

(涵盖基础、爬虫、数据分析、web开发、机器学习、人工智能、面试题)、Python学习路线图等等

直接在文末名片自取即可!

有更多建议或问题可以评论区或私信我哦!一起加油努力叭(ง •_•)ง

喜欢就关注一下博主,或点赞收藏评论一下我的文章叭!!!

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

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

相关文章

redis之作为缓存使用

写在前面 Redis因为其自身高性能的数据读取能力&#xff0c;因此会经常被应用到缓存的场景中&#xff0c;本文就一起看下Redis当做缓存使用时的特点&#xff0c;问题&#xff0c;以及需要注意的点。 1&#xff1a;缓存的架构模式 从架构模式上来看缓存系统可以分为旁路缓存&…

Kotlin 基础学习笔记第八章——高阶函数:Lambda作为形参和返回值

一、声明高阶函数 高阶函数定义&#xff1a;高阶函数就是以另一个函数作为参数或者返回值的函数。 在kotlin中&#xff0c;函数可以用lambda或者函数引用来表示。因此&#xff0c;任何以lambda或者函数引用作为参数的函数&#xff0c;或者返回值为lamda或函数应用的函数&#x…

基于遗传算法优化的lssvm回归预测-附代码

基于遗传算法优化的lssvm回归预测 - 附代码 文章目录基于遗传算法优化的lssvm回归预测 - 附代码1.数据集2.lssvm模型3.基于遗传算法优化的LSSVM4.测试结果5.Matlab代码摘要&#xff1a;为了提高最小二乘支持向量机&#xff08;lssvm&#xff09;的回归预测准确率&#xff0c;对…

使用openshift 进行云平台连接

使用openshift 进行云平台连接 OpenShift CLI on Windows openshift 文档地址 OpenShift CLI on Mac 通过Homebrew方式安装 brew install openshift-cli安装完成&#xff0c;进行验证 oc version服务连接 oc login 服务地址根据提示输入用户名和密码&#xff0c;即可连接…

某讯滑块验证码反汇编分析-第一章

某讯滑块验证码反汇编分析-第一章js分析初步分析vmp结构js分析 在滑动完成后&#xff0c;会请求【cap_union_new_verify】接口&#xff0c;其中有5个比较长的参数&#xff0c;看起来可能会有加密的&#xff0c;分别如下。 参数名来源uasesscollecteksvData 那现在js看看这些参…

让车机「下雨」,路特斯的智能座舱跑偏了吗?

HIEV消息&#xff08;文/张祥威&#xff09;“我们今天用双8155&#xff0c;都觉得&#xff08;算力&#xff09;还不够。”杨平说。 这位路特斯的智能座舱研发负责人&#xff0c;目前带领着一支两百多人的团队&#xff0c;为Eletre这款车操刀座舱智能化。 双8155&#xff0c;指…

Gitee应用(1):快速搭建Git环境在不同电脑同步文件

一、前言 环境&#xff1a;Windows 11 64位 &#xff1b;vscode&#xff1a;1.73.1 当你要操作在两台不同的电脑上操作&#xff0c;或许经常会遇到一个问题&#xff0c;就是怎么同步同一个或几个文件&#xff0c;以方便你在不同的电脑上进行同个文件内容的创作。 在申请了公司电…

【Java难点攻克】「NIO和内存映射性能提升系列」彻底透析NIO底层的内存映射机制原理与Direct Memory的关系

NIO与内存映射文件 Java类库中的NIO包相对于IO包来说有一个新功能就是 【内存映射文件】&#xff0c;在业务层面的日常开发过程中并不是经常会使用&#xff0c;但是一旦在处理大文件时是比较理想的提高效率的手段&#xff0c;之前已经在基于API和开发实战角度介绍了相关的大文…

Java Math类

JavaMath类\huge{Java \space Math类}Java Math类 Math类 包含执行基本数字运算的方法&#xff0c;Math类没有提供公开的构造器。 MathMathMath类本质就是一个工具类&#xff0c;提供许多方法用于其他类调用&#xff0c;但是无法创建子类对象。 常用方法 ①. abs()取绝对值…

CANoe测试的两种方式Test Module 和 Test Unit对比,你常用哪种呢?

&#x1f345; 我是蚂蚁小兵&#xff0c;专注于车载诊断领域&#xff0c;尤其擅长于对CANoe工具的使用&#x1f345; 寻找组织 &#xff0c;答疑解惑&#xff0c;摸鱼聊天&#xff0c;博客源码&#xff0c;点击加入&#x1f449;【相亲相爱一家人】&#x1f345; 玩转CANoe&…

前端接口联调时传的参数是array数组形式处理

情景&#xff1a;使用van-uolaoder组件上传多个图片后调用保存按钮&#xff0c;这时由于存在多张图片&#xff0c;调用接口时前端传的参数就是数组形式。&#xff08;前端传的数组要先转为字符串&#xff09; 处理方法是&#xff1a; 1. 先确定后端使用什么注解&#xff0c;如…

Gerb视图支持新表单和旧表单

Gerb视图支持新表单和旧表单 GerbView生产高级软件Companions&#xff0c;但也易于替换、打印和查看HPGL、HPGL/2、Excellon和国际象棋文件。该程序支持RS274D和RS274X。您可以使用此软件将旧格式和标准RS274D转换为具有默认信息的新类型RS274X。Gerbview将致力于展示和绘制您的…

计算机毕业设计django基于python租房系统-房屋租赁系统

项目介绍 在各学校的教学过程中,租房系统是一项非常重要的事情。随着计算机多媒体技术的发展和网络的普及。采用当前流行的B/S模式以及3层架构的设计思想通过Python技术来开发此系统的目的是建立一个配合网络环境的租房系统的平台,这样可以有效地解决租房系统混乱的局面。 本文…

(P3)python类的特殊方法 init、getitem、len、call

python 类的特殊方法 参考资料 python解释器遇到特殊句法时&#xff0c;会去调用特殊方法&#xff0c;这些特殊方法以双下划线开头。 1、__init __ () 该方法在对象创建时被解释器自动调用。 2、__getitem __ () getitem 获取实例对象的具体内容 p[key] 3、__len __() len …

牛客挑战赛65 D.233求min(二维偏序 树状数组/cdq分治)

题目 给出长度为n(n<1e5)的序列a1,a2,...,an​和b1,b2,...,bn(-1e3<ai,bi<1e3)&#xff0c; 请你找出1≤l≤r≤n&#xff0c;使得min(alal1...ar, blbl1...br)最大&#xff0c;并输出这个值 思路来源 官方题解 LYC_music submission 题解 两种做法&#xff0c; …

Python模块和包的介绍(模块含义、用模块好处、模块分类、包和模块的创建)

&#x1f308; 个人主页&#xff1a;王子玉博客 &#x1f506; 免费专栏&#xff1a;Python基础教程、python常用模块 ❤️ 分享网站&#xff1a; 《Python自学网》&#x1f449;&#x1f449;基础入门到逐步深入 | 适合新手入门到精通 | web开发、爬虫、自动化运维、自动化…

yocto 自动挂载分区(基于stmp32mp1)

yocto 自动挂载分区&#xff08;基于stmp32mp1&#xff09; 上一章我们在stm32mp1开发板上实践了创建分区的过程&#xff0c;本节我们再来分析下上小节创建的分区开机时是怎么完成分区的自动挂载的。 答案就在systemd里面&#xff1a; 下面就来详细分析一下这个几个文件 mo…

C/C++入门003-C语言变量与运算符

文章目录变量常量的概念常量的类型变量的概念定义变量为什么要定义变量如何使用变量&#xff1f;变量初始化修改变量变量之间的值传递如何查看变量的值?变量的作用域printf函数scanf函数函数的参数运算符算数运算符赋值运算符sizeof运算符逗号运算符关系运算符逻辑运算符三目运…

攻击类型的攻击次数分布

攻击类型分析 2018 年&#xff0c;主要的攻击类型 1 为 SYN Flood&#xff0c;UDP Flood&#xff0c;ACK Flood&#xff0c;HTTP Flood&#xff0c;HTTPS Flood&#xff0c; 这五大类攻击占了总攻击次数的 96&#xff05;&#xff0c;反射类攻击不足 3%。和 2017 年相比&…

【Linux网络编程】select多路复用

文章目录前言如何增强服务端的通信能力Linux的设计哲学文件描述符代码讲解以文件方式操作命令行阻塞函数与非阻塞函数轮询select()代码全貌The End前言 我们上节课讲解了服务端的编程(Linux服务端编程初体验) 本节课要讲的是select 提示&#xff1a;以下是本篇文章正文内容&am…