吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 7597|回复: 106
收起左侧

[Python 原创] 笔趣阁小说爬取程序,100线程秒速下载

  [复制链接]
pnnhnjh 发表于 2024-11-27 14:39
本帖最后由 pnnhnjh 于 2025-3-1 22:41 编辑

    本程序下载小说时会出现不少问题,请停止使用。如有需求,请移步到新贴下载,新帖标题为 弟子小说爬取程序,100线程秒速下载 ”(https://www.52pojie.cn/forum.php?mod=viewthread&tid=2010642&page=1&extra=#pid52496137)


笔趣阁小说爬取程序,100线程极速下载,示例的小说610章,128万字,15秒左右下载完成!运行后打开网站,选取你喜欢的小说,打开小说的目录页面(小说目录页),复制网址(如:https://www.bigee.cc/book/59507/)后粘贴到输入提示窗口回车即可。注:不输入任何内容直接回车则开始示例小说下载!




[Python] 纯文本查看 复制代码
import os
import re
import random
import time
import requests
import threading
from queue import Queue
from lxml import etree
from requests.adapters import HTTPAdapter

# 用户代{过}{滤}理列表
user_agents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18363',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36',
    'Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1'
]

# 增加连接池大小
session = requests.Session()
adapter = HTTPAdapter(pool_connections=100, pool_maxsize=100)  # 设置连接池大小为100
session.mount('http://', adapter)
session.mount('https://', adapter)


def get_chaptercontent(chapter_url, temp_file, queue, semaphore, session, max_retries=5):
    semaphore.acquire()  # 获取信号量
    try:
        retry_count = 0
        chaptercontent = ''
        while retry_count < max_retries:
            try:
                time.sleep(0.2)
                headers = {
                    'User-Agent': random.choice(user_agents),
                    'Accept-Language': 'en-US,en;q=0.9'
                }
                response = session.get(chapter_url, headers=headers, timeout=60)
                response.close()  # 确保连接关闭
                if response.status_code == 429:
                    wait_time = int(response.headers.get('Retry-After', 2))  # 尝试从响应头获取等待时间
                    time.sleep(wait_time)
                    continue

                if response.status_code != 200:
                    if retry_count == max_retries - 1:
                        print(f"未能获取章节: {chapter_url} - 状态码: {response.status_code}")
                    queue.put(None)  # 标记失败
                    return

                # 使用lxml解析响应文本
                html = response.content.decode(response.apparent_encoding)
                selector = etree.HTML(html)
                title = selector.xpath('//div[@class="content"]/h1/text()')
                contents = selector.xpath('//div[@id="chaptercontent"]/text()')

                for content in contents:  # 把每一段内容连接起来
                    chaptercontent += '\n  ' + str(content).strip()

                chaptercontent = re.sub(r'请收藏.*?m.bigee.cc', '', chaptercontent,
                                        flags=re.S)  # 去掉正文里面广告,可以垮段,中间的*?为通配符
                chaptercontent = re.sub(r'[\s ]{0,6}第.{1,10}[部分章节卷页]{1,2}.{0,30}[\s \n]{0,6}',
                                        '', chaptercontent)  # 去掉正文里面第字开头、部分章节卷结尾、小于一定长度的段
                # chaptercontent = re.sub(r'[\s ]{0,6}\d{1,5}.{1,30}[\s \n]{0,6}',
                #                         '', chaptercontent)  # 去掉正文里面数字开头、小于一定长度的段
                # chaptercontent = re.sub(r'[  ]{1,}', '', chaptercontent)  # 去掉所有半角和全角空格

                if not title or not contents:
                    if retry_count == max_retries - 1:
                        print(f"未能找到章节内容: {chapter_url}")
                    queue.put(None)  # 标记失败
                    return

                title = title[0]  # 假设只有一个标题
                print(f"\t正在下载:{title}")

                # 将章节标题和内容写入临时文件
                with open(temp_file, 'w', encoding='utf-8') as f:
                    f.write(title + '\n\n')
                    f.writelines(chaptercontent)

                queue.put(temp_file)  # 将文件路径放入队列
                break  # 成功后退出循环
            except requests.exceptions.RequestException as e:
                retry_count += 1
                if retry_count == max_retries:
                    print(f"达到最大重试次数,未能下载章节: {chapter_url} - 错误: {e}")
                    queue.put(None)  # 标记失败
                    return
                else:
                    time.sleep(5)  # 等待5秒后重试

        if retry_count == max_retries:
            queue.put(None)  # 标记失败
    finally:
        semaphore.release()  # 无论成功还是失败,都释放信号量


def download_chapters(base_url):
    retry_count = 0
    max_retries = 5  # 最大尝试次数
    while retry_count < max_retries:
        try:
            response = session.get(base_url, headers={'User-Agent': random.choice(user_agents)}, timeout=60)
            response.close()  # 确保连接关闭
            if response.status_code != 200:
                if retry_count == max_retries - 1:
                    print(f"未能获取URL: {response.status_code}")
                return

            # 使用lxml解析响应文本
            html = response.content.decode(response.apparent_encoding)
            selector = etree.HTML(html)
            chapter_links = selector.xpath('//dd/a/@href')

            if not chapter_links:
                if retry_count == max_retries - 1:
                    print("未找到章节链接。")
                return

            # 获取书籍名称
            book_name = selector.xpath('//h1/text()')[0]
            print(f'\n正在下载小说:{book_name}\n')

            save_directory = os.path.join(os.getcwd(), '我的小说')  # 当前目录下的 "downloads" 文件夹
            os.makedirs(save_directory, exist_ok=True)  # 创建保存目录

            # 创建一个队列来保存结果
            result_queue = Queue()

            # 定义 semaphore
            semaphore = threading.BoundedSemaphore(max_threads)  # 对应最大线程数

            threads = []

            # 遍历章节链接,剔除多余的不需要的章节链接
            for index, href in enumerate(chapter_links[0:-5], start=1):
                if href != "javascript:dd_show()":
                    chapter_url = f'https://www.bigee.cc{href}'
                temp_file = os.path.join(save_directory, f'temp_{index:04d}.txt')

                # 创建线程来下载章节内容
                thread = threading.Thread(target=get_chaptercontent,
                                          args=(chapter_url, temp_file, result_queue, semaphore, session, max_retries))
                threads.append(thread)
                thread.start()

            # 等待所有线程完成
            for thread in threads:
                thread.join()

            # 从队列中收集结果
            temp_files = []
            while not result_queue.empty():
                temp_file = result_queue.get()
                if temp_file:  # 如果文件成功创建
                    temp_files.append(temp_file)

            # 按章节顺序对临时文件排序
            temp_files.sort(key=lambda x: int(x.split('_')[-1].split('.')[0]))

            # 合并临时文件到主文件
            append_temp_files_to_main(temp_files, save_directory, book_name)
            break  # 成功后退出循环
        except requests.exceptions.RequestException as e:
            retry_count += 1
            if retry_count == max_retries:
                print(f"达到最大重试次数,未能下载章节列表。 - 错误: {e}")
                return
            else:
                time.sleep(5)  # 等待5秒后重试

    if retry_count == max_retries:
        print(f"达到最大重试次数,未能下载章节列表。")


def append_temp_files_to_main(temp_files, save_directory, book_name):
    book_path = os.path.join(save_directory, f'{book_name}.txt')
    with open(book_path, 'w', encoding='utf-8') as main_file:
        for temp_file in temp_files:
            with open(temp_file, 'r', encoding='utf-8') as tf:
                chapter_text = tf.read().strip()
                if chapter_text:  # 确保章节文本非空
                    main_file.write(chapter_text + '\n\n')
            os.remove(temp_file)  # 删除临时文件


if __name__ == "__main__":
    base_url = 'https://www.bigee.cc/'
    url = input(f"请输入网站({base_url})内选定小说目录页所在页网址:")
    max_threads = 100  # 设置最大线程数
    if url == '':
        url = 'https://www.bigee.cc/book/59507/'
    start_time = time.time()
    download_chapters(url)
    end_time = time.time()
    print(f'\n总耗时:{end_time - start_time:.2f}秒。\n')
    input("下载完成,小说保存在“我的小说”文件夹内,回车退出!")




编译后下载地址:链接:https://pan.baidu.com/s/1PaKjSIg9KBXwXyeRiismwQ
提取码:52pj

免费评分

参与人数 13吾爱币 +18 热心值 +8 收起 理由
hshcompass + 1 热心回复!
pqjhhh + 1 + 1 能用,很快,可惜向看的小说每章只有一半,给作者点赞
cfx0619 + 1 + 1 谢谢@Thanks!
又是馒头 + 1 + 1 有人分流下蓝奏嘛?
smaio + 1 + 1 热心回复!
sjb5201314 + 1 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
kymql24 + 1 谢谢@Thanks!
sngss + 1 谢谢@Thanks!
h94666 + 1 谢谢@Thanks!
hscxdesign + 1 用心讨论,共获提升!
grifth + 1 + 1 谢谢@Thanks!
gqdsc + 1 谢谢@Thanks!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

 楼主| pnnhnjh 发表于 2024-11-30 17:46
lianghaijian 发表于 2024-11-30 12:33
我下载的小说为啥内容不对啊    你们的都对吗?

把网址贴出来看看,现在下载都是正常的!

请输入网站(https://www.bigee.cc/)内选定小说目录页所在页网址:https://www.bigee.cc/book/3140/

正在下载小说:医武兵王

        正在下载:第1章 美女总裁
        正在下载:第5章 暴力警花
        正在下载:第8章 大明星的委屈
。。。。。。
。。。。。。
        正在下载:第四千三百七十二章 委曲求全
        正在下载:第四千三百八十五章 没有退路
        正在下载:第四千三百六十五章 巧克力
        正在下载:第四千三百七十八章 太天真、太单纯
        正在下载:第四千三百五十八章 针到病除

总耗时:115.09秒。

下载完成,小说保存在“我的小说”文件夹内,回车退出!
2024-11-30_174342.jpg
sjb5201314 发表于 2025-1-18 17:03
下载的内容不完整是因为网址的问题。
www.bigee.cc/book/这个路径下的章节内容有缺失,有时打开章节能显示完整的内容,发现是跳转到了另一个网址。目前程序无法手动修改网址,导致下载的书本各个章节内容都不完整。
bz1wsq 发表于 2024-11-27 14:46
楼主你好萌 发表于 2024-11-27 14:46
网站已经挂了
zicheng5 发表于 2024-11-27 14:48
多看多学
banzhuren 发表于 2024-11-27 14:52
网站已经挂了
qq1475 发表于 2024-11-27 14:55
直接火车头采集就行
 楼主| pnnhnjh 发表于 2024-11-27 14:58

能用,没挂
或许舞恋步 发表于 2024-11-27 14:58
亲测14.41s,大佬牛掰
开创者 发表于 2024-11-27 15:01
qq1475 发表于 2024-11-27 14:55
直接火车头采集就行

火车没有这么快啊,这个多快啊。不过我不明白为什么大家都喜欢搞小说。
heavenman 发表于 2024-11-27 15:02
谢谢作者贴出原创作品! 学习。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-5-10 14:10

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表