吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2205|回复: 32
收起左侧

[其他原创] PHP作的一个有声小说抓取批量下载工具。

[复制链接]
hc3w 发表于 2024-1-7 13:29
本帖最后由 hc3w 于 2024-1-8 08:59 编辑

有声小说URL地址是:aHR0cHMlM0EvL3d3dy55c3RzLmNjL3RpbmdzaHUvMTA5MjMv

@huanling8866 求下载的一个,作了一个批量下载工具,源代码如下:

运行效果,使用PHP开发,开源,



可以修改专ID如下图。
微信截图_20240107132713.jpg

dw.png

源代码如下:
(2024年1月7号20:20分更新) 增加了判断 更新太快, 有提示时,更换IP 可以继续下载。

(2024年1月8号9:0分更新)增加了cookies,需要自己更新抓取。

下载压缩包的,自己更新一下这个PHP代码。
sleep 是超时时间单位为秒。

[PHP] 纯文本查看 复制代码
<?php
ini_set("max_execution_time", "9000");
ini_set("pcre.backtrack_limit",-1);
ini_set("pcre.recursion_limit",-1);
ignore_user_abort(true);
set_time_limit(0);
ini_set("memory_limit", "-1");
header('Content-Type: text/html; charset=UTF-8');
error_reporting(E_ALL);
ini_set("display_errors", 1);
$page_f="pageid_.txt";
if(file_exists($page_f))
{
        $page=file_get_contents($page_f);
        if($page!=""){$page=$page+1;}else{$page=1;}
}
else
{
        $page=1;
}
#这里是专辑ID
$id=10923;
#这里63是全部页面结束页
if($page>63){echo "全部下载完成";die();}

#下面不要改动
if(file_exists("cookie.txt")){@unlink("cookie.txt");}
$url="https://www.ysts.cc/tingshu/{$id}/?p={$page}";
$header = [
        'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ja;q=0.5,zh-TW;q=0.4',
        'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
        'Content-Type: application/x-www-form-urlencoded; charset=UTF-8',
        'Origin: http://www.ysts.cc',
        "Referer: https://www.ysts.cc/tingshu/{$id}/41440.html",
];
$param =array();
$res = http($url,$param,'GET',$header);
$a_rule = '/<a href="\/tingshu\/'.$id.'\/(\d+)\.html" target="_blank" title="([^"]+)">/s';
preg_match_all($a_rule, $res, $matchA);
$num = count($matchA);
if (empty($matchA[$num-1])){
    exit("未获取");
}
foreach ($matchA[0] as $k=>$v)
{
        $mid=$matchA[1][$k];
        $name=$matchA[2][$k];
        $url="https://www.ysts.cc/tingshu/{$id}/{$mid}.html";
        $param =array();
        $res = http($url,$param,'GET',$header);
        $a_rule = '/<meta name="_c" content="([^"]+)" \/>/s';
        preg_match_all($a_rule, $res, $matchB);
        $num = count($matchB);
        if (empty($matchB[$num-1])){
            exit("未获取SC");
        }
        $sc=$matchB[1][0];
        $url="https://www.ysts.cc/api/act/play";
        $header1=$header;
        $header1[]="sc:{$sc}";
        $param =array('nid'=>$id,'cid'=>$mid);
        echo "{$name}...";
         #下面代码是修改过的,防止太快。
        while(true)
        {
                $res =json_decode(http($url,$param,'POST',$header1),true);
                if($res['url']!="")
                {
                        $param=array();
                        $m4a =http($res['url'],$param,'POST',$header1);
                        @file_put_contents("m4a/".$name.".m4a",$m4a);
                        echo "下载ok!\n";
                        break;
                }
                else{
                        echo "太快了,请更换IP地址,或等100秒";
                        sleep(100);
                }
        }
}
file_put_contents($page_f,$page);
die();
function http($url, $params, $method = 'GET', $header = array(), $multi = false,$cookies=""){
        if(file_exists("cookie.txt") && $cookies=="")
        {
                $cookies=file_get_contents("cookie.txt");
        }

	#用户:52pjcn  密码:52pjcn  使用 Fiddler来抓取cookies,获取的cookies有效期24小时.
	$cookies="PTCMS_userid=6291; PTCMS_username=52pjcn; PTCMS_token=9eae72b8550b1cada1cc9da68d318ef3";

    $opts = array(
        CURLOPT_CONNECTTIMEOUT        => 15,
        CURLOPT_TIMEOUT        => 15,
        CURLOPT_RETURNTRANSFER => 1,
        CURLOPT_SSL_VERIFYPEER => false,
        CURLOPT_SSL_VERIFYHOST => false,
        CURLOPT_HTTPHEADER     => $header,
        CURLOPT_FOLLOWLOCATION=> 1,
        CURLOPT_COOKIESESSION =>1,
        CURLOPT_AUTOREFERER =>1,
    );
    if(strtoupper($method)=="GET")
    {
            $opts[CURLOPT_HEADER] =1;
    }
    if($cookies!="")
    {
            $opts[CURLOPT_COOKIE] =$cookies;
    }
    switch(strtoupper($method)){
        case 'GET':
            $opts[CURLOPT_URL] = $url . '?' . http_build_query($params);
            break;
        case 'POST':
            $params = $multi ? $params : http_build_query($params);
            $opts[CURLOPT_URL] = $url;
            $opts[CURLOPT_POST] = 1;
            $opts[CURLOPT_POSTFIELDS] = $params;
            break;
        default:
            throw new Exception('不支持的请求方式!');
    }
    $ch = curl_init();
    curl_setopt_array($ch, $opts);
    $data  = curl_exec($ch);
    $error = curl_error($ch);
    curl_close($ch);
    if($error) throw new Exception('请求发生错误:' . $error);
        if(strtoupper($method)=="GET")
        {
                preg_match('/^Set-Cookie: (.*?);/im', $data, $m);
                if(isset($m[1]))
                {
                        @file_put_contents("cookie.txt",$m[1]);
                }
        }
    return  $data;
}

?>


成品代码如下:双击u.bat 下载,感觉好用给点CB。

down.part1.rar (2.8 MB, 下载次数: 106)

down.part2.rar (2.11 MB, 下载次数: 93)

免费评分

参与人数 7吾爱币 +13 热心值 +6 收起 理由
san123872 + 1 + 1 谢谢@Thanks!
zxl4689 + 1 + 1 鼓励转贴优秀软件安全工具和文档!
bonkers123 + 2 谢谢@Thanks!
zhangsan2022 + 1 谢谢@Thanks!
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
huanling8866 + 1 + 1 刚试了试,下载了第一页后,后边就是0字节。网站有限制?
blindcat + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

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

 楼主| hc3w 发表于 2024-1-7 20:23
huanling8866 发表于 2024-1-7 20:11
就是我把63改成2,就是从第2页开始下还是就下两页这样子?我的意思是我想下第3页吧比如,或者下3-6页这样 ...

pageid_.txt 这里就是开始页号,要-1 ,比如:第二页,保存的就是1  ,代码更新了一下。增加了提示。更换IP
最新的 发表于 2024-1-7 16:06
是否可以将你的代码修改为python版,单独发一个贴,会标明来源
山田凉粉 发表于 2024-1-7 14:49
zhangjie0506 发表于 2024-1-7 15:00
下下来的第一集是 二楞子在线收听
blindcat 发表于 2024-1-7 16:49
感谢分享,学习一下
 楼主| hc3w 发表于 2024-1-7 17:06
最新的 发表于 2024-1-7 16:06
是否可以将你的代码修改为python版,单独发一个贴,会标明来源

欢迎,没有问题。
最新的 发表于 2024-1-7 17:20
本帖最后由 最新的 于 2024-1-7 17:25 编辑

[Python] 纯文本查看 复制代码
# **************************************************
# 免责声明:
# 本代码仅供学习和研究使用,严禁用于任何商业用途。
# 作者不对使用本代码导致的任何后果负责。
# 在使用本代码时,请遵守相关法律法规和网站的使用规定。
# **************************************************

import os
import tkinter as tk
from tkinter import simpledialog
import requests
import re
import json

# ANSI转义码
class Colors:
    RED = '\033[91m'
    YELLOW = '\033[93m'
    GREEN = '\033[92m'
    ENDC = '\033[0m'

def clean_filename(filename):
    # 移除非法字符
    return re.sub(r'[\/:*?"<>|]', '', filename)

def download_novel(id, page_num):
    current_page_file = "pageid_.txt"

    # 提示用户输入当前页数
    current_page = simpledialog.askinteger("输入", "请输入从第几页开始下载:")

    if current_page is None:
        print(Colors.RED + "未输入当前页数,退出下载" + Colors.ENDC)
        return

    if current_page > page_num:
        print(Colors.GREEN + "全部下载完成" + Colors.ENDC)
        return

    base_url = "https://www.ysts.cc/tingshu"
    session = requests.Session()

    url = "{}/{}/?p={}".format(base_url, id, current_page)
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6,ja;q=0.5,zh-TW;q=0.4',
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0',
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
        'Origin': 'http://www.ysts.cc',
        'Referer': '{}/{}/41440.html'.format(base_url, id),
    }

    try:
        response = download_file(session, url, headers)
        a_rule = fr'<a href="/tingshu/{id}/(\d+)\.html" target="_blank" title="([^"]+)">'
        match_a = re.findall(a_rule, response.text, re.S)

        if not match_a:
            print(Colors.RED + "未获取到数据,请检查输入参数是否正确!" + Colors.ENDC)
            return

        # 创建整个音频的保存路径
        folder_path = os.path.join("Novel audio")
        os.makedirs(folder_path, exist_ok=True)

        for match in match_a:
            mid = match[0]
            name = match[1]
            name_cleaned = clean_filename(name)
            url = "{}/{}/{}.html".format(base_url, id, mid)
            response = download_file(session, url, headers)
            c_rule = r'<meta name="_c" content="([^"]+)" />'
            match_b = re.findall(c_rule, response.text, re.S)

            if not match_b:
                print(Colors.RED + "未获取SC" + Colors.ENDC)
                return

            sc = match_b[0]
            play_url = "https://www.ysts.cc/api/act/play"
            headers_play = headers.copy()
            headers_play["sc"] = sc
            print(f"{name}...")

            params_play = {'nid': id, 'cid': mid}
            response_play = session.post(play_url, headers=headers_play, data=params_play, timeout=60)
            response_play.raise_for_status()

            # Check if the response is JSON
            if 'application/json' in response_play.headers['content-type']:
                try:
                    result_play = response_play.json()
                except json.JSONDecodeError:
                    print(Colors.RED + "未能正确解析JSON响应" + Colors.ENDC)
                    return
            else:
                print(Colors.RED + "未获取正确的播放数据" + Colors.ENDC)
                return

            novel_title_rule = r'<title>(.*?)</title>'
            novel_title_match = re.search(novel_title_rule, response.text)

            if novel_title_match:
                novel_title = clean_filename(novel_title_match.group(1).strip())
            else:
                print(Colors.RED + "未获取小说标题" + Colors.ENDC)
                return

            # 检查文件是否已存在
            audio_file_path = os.path.join(folder_path, f"{name_cleaned}.m4a")
            if os.path.exists(audio_file_path):
                print(Colors.YELLOW + f"此音频文件已存在,跳过下载!" + Colors.ENDC)
            else:
                # 保存音频文件
                with open(audio_file_path, "wb") as file:
                    file.write(download_file(session, result_play['url'], headers_play, timeout=60).content)
                print(Colors.GREEN + "此音频下载完成!\n" + Colors.ENDC)

        # 将 "全部下载完成" 移到循环外部
        print(Colors.GREEN + "全部下载完成" + Colors.ENDC)

        # 将当前页数写入文件
        with open(current_page_file, "w") as file:
            file.write(str(current_page))
    except KeyboardInterrupt:
        print(Colors.YELLOW + "下载已被用户中断!" + Colors.ENDC)
    except Exception as e:
        print(Colors.RED + f'下载失败:{str(e)}' + Colors.ENDC)

def download_file(session, url, headers, params=None, method='GET', timeout=30):
    response = session.request(method, url, headers=headers, params=params, timeout=timeout)
    response.raise_for_status()
    return response

def main():
    root = tk.Tk()
    root.withdraw()  # 不显示 tkinter 窗口

    try:
        album_id = simpledialog.askinteger("输入", "请输入专辑ID:")
        page_num = simpledialog.askinteger("输入", "请输入总下载页数:")
        download_novel(album_id, page_num)
    except KeyboardInterrupt:
        print(Colors.YELLOW + "下载已被用户中断!" + Colors.ENDC)
    except Exception as e:
        print(Colors.RED + f'下载失败:{str(e)}' + Colors.ENDC)

if __name__ == "__main__":
    main()


使用方法

  1. 运行脚本时,输入专辑 ID 和下载页数。
  2. 脚本会自动下载指定专辑的音频,并保存到名为 "Novel audio" 的文件夹中。
  3. 在下载过程中,可以通过键盘中断(Ctrl+C)来停止下载。

主要特点

  • 交互式输入: 使用 Tkinter 提供的简单对话框,用户可以轻松输入专辑 ID 和下载页数。
  • 下载续传: 脚本支持从指定页数继续下载,避免重复下载已有音频。
  • 下载进度提示: 在下载过程中,脚本会输出当前下载的音频信息,包括音频标题和下载状态。
  • 文件存在检查: 在下载前会检查音频文件是否已存在,避免重复下载相同的音频。
  • 异常处理: 对可能的异常情况进行了处理,包括网络请求失败、JSON 解析错误等。
  • 输出着色: 使用 ANSI 转义码实现输出文字的着色,以区分不同类型的输出信息。例如,错误信息为红色,警示信息为黄色,成功信息为绿色。
  • 用户中断处理: 用户可以通过 Ctrl+C 中断下载,并会有相应的提示。

注意事项

  • 请确保使用脚本的行为符合相关网站的使用协议。
  • 下载过程中可能会因网络原因导致下载失败,可以重新运行脚本进行续传。

希望这个脚本能够方便你获取喜欢的小说音频,祝你使用愉快!

免费评分

参与人数 1吾爱币 +2 热心值 +1 收起 理由
hc3w + 2 + 1 我很赞同!

查看全部评分

最新的 发表于 2024-1-7 17:37
hc3w 发表于 2024-1-7 17:06
欢迎,没有问题。

好的,感谢!
CQGaxm 发表于 2024-1-7 17:59
感谢分享,
huanling8866 发表于 2024-1-7 20:07
刚用楼主开发的试用了一下,前边第一页30集的正常下来,后边的就都是0字节,然后都有好多章节跳的。是不是网站有限制,从哪里改就是我可以一页一页的下。改PAGE那里吗?比如从几页下到几页之类的?
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

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

GMT+8, 2024-4-29 07:36

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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