本文由 简悦 SimpRead 转码, 原文地址 real7.blog.csdn.net

环境:IOS 想使用 换源阅读问题:换新手机,源阅读下架后,没有好的 APP 阅读小说解决办法:自签 APP + 转换源仓库书源背景:自从我换了新 iPhone 手机,就无法使用 IOS 版源阅读了,我也试过各种书香,各种石头,各种万源阅读,但都有广告,兼容性也不好,于是我自签了一个源阅读用上,结果发现现在的书源发展的很快,旧版本的源阅读 APP 部分书源的语法不支持,于是我反复总结对比,写了一个自动转换的 python 程序,如上链接解决过程:自签 APP + 转换书源。

环境:IOS 想使用 换源阅读
问题:换新手机,源阅读下架后,没有好的 APP 阅读小说
解决办法:自签 APP + 转换源仓库书源

最终预览 :https://rc.real9.cn/

背景:自从我换了新 iPhone 手机,就无法使用 IOS 版源阅读了,我也试过各种书香,各种石头,各种万源阅读,但都有广告,兼容性也不好,于是我自签了一个源阅读用上,结果发现现在的书源发展的很快,旧版本的源阅读 APP 部分书源的语法不支持,于是我反复总结对比,写了一个自动转换的 python 程序,如上链接

解决过程:自签 APP + 转换书源

  1. 下载 源阅读 ipa:

下载地址
https://wwrw.lanzoub.com/iCpju13d27eb
密码: 8rx4

  1. 自签 IPA:

自签我试过三种:

  1. 企业证书自签,免费,需要自己去找网上的企业证书,大多坚持 2 周就挂了,放弃
  2. 个人开发者证书自签,免费,但是 7 天就要续签一次,可以使用牛蛙助手自签,但是广告多到爆,简直是牛皮鲜,放弃
  3. 个人 UUID 自签,某宝 20 买的,是目前的方案,看运气,能用半年

关于怎么自签,你们可以用轻松签、全能签,小白啥也不会就用爱思助手,我放张图你们就能懂了。



签完了把签好的 APP,拖我的应用就能自动安装

  1. 转换书源

3.1 获得书源

提供两个源仓库:
https://www.yckceo.com/yuedu/shuyuan/index.html
https://yuedu.miaogongzi.net/

3.2 转换规则

由于这款源阅读 APP 版本是 2021 年左右的,很多新版书源不支持,我们要进行转换,我自己花了点时间总结了一点转换规则:

最常见的规则是不支持 a.1@text 这种,要转换,其他参考下列

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
书源类型
0 文本
2 视频
3 漫画
1 音频
-------------------------------
# 选择ID
. 选择元素 class之类
> 子元素
~ 第二个,兄弟元素,同级关系
p:nth-child(2) 父元素的第n个子元素
[] 属性选择器 [class^=book] 选择class以book开头的元素
! 倒序选择器 img:!-1 选择最后一个img元素
|| 列组合选择器 col||td 选择col和td元素
( ) 分组选择器 (div,p) 选择所有div和p
, 多个选择器 .item, .active 选择item和active类
* 通用元素选择器 *.item 选择所有类名包含item的元素
n 表达式选择器 li:nth-child(3n) 按序选择li元素,每个li元素的父元素中的第 3、6、9、12等序号
a.-1@text 改为a:nth-last-child(1)@text
a.1@text a:nth-child(1)@text```

### 3.3 步骤3.3

3.3 转换书源

现在开始转换,笨的办法是用记事本替换,我写了个 python 脚本来自动替换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import json
import requests

def replace_selectors(json_data):
# 替换选择器的函数
def replace_selector(selector):
if "." in selector and "@" in selector:
parts = selector.split('.')
tag = parts[0]
selector_part = parts[1]
if "@" in selector_part:
num, at_text = selector_part.split('@', 1)
if ":" in num:
num, tag_after_colon = num.split(':', 1)
num = f"{num}@{tag_after_colon}"
if num.replace("-", "").replace(".", "").isdigit():
num = "1" if num == "0" else num # 处理小数点后面是0的情况
if num.startswith("-"):
num = num[1:]
return f"{tag}:nth-last-child({num})@{at_text}"
else:
return f"{tag}:nth-child({num})@{at_text}"
return selector

# 处理列表类型的 JSON 数据
if isinstance(json_data, list):
for item in json_data:
replace_selectors(item)
return

# 遍历字典类型的 JSON 数据,查找并替换选择器
for key, value in json_data.items():
if isinstance(value, str):
if "@" in value:
value = replace_selector(value)
json_data[key] = value
elif isinstance(value, dict):
replace_selectors(value)
elif isinstance(value, list):
for item in value:
if isinstance(item, dict):
replace_selectors(item)

# 增加替换规则,当"ruleExplore": []时,替换为"ruleExplore": "##"
if "ruleExplore" in json_data and not json_data["ruleExplore"]:
json_data["ruleExplore"] = "##"

if __name__ == "__main__":
# 用户输入 JSON 文件的 URL
json_url = input("请输入 JSON 文件的 URL: ")

# 下载 JSON 数据
response = requests.get(json_url)
json_data = response.json()

# 替换选择器
replace_selectors(json_data)

# 提取文件名,并保存 JSON 内容到文件
file_name = json_url.split('/')[-1]
with open(file_name, 'w', encoding='utf-8') as file:
json.dump(json_data, file, indent=4, ensure_ascii=False)

print(f"JSON 内容已按照新的替换原则进行替换并保存为文件:{file_name}")
  1. 在线转换

本地转换有点麻烦,我玩手机的时候电脑又不会一直在身边,我就把上面的代码改成了 web 版本,这些复制转换后的连接,到 APP 剪贴板导入就好了,效果如下:

4.1 web 版源代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import json
import os
import requests
from flask import Flask, render_template, request, send_from_directory, url_for
from werkzeug.utils import secure_filename

app = Flask(__name__)

def replace_selectors(json_data):
# 替换选择器的函数
def replace_selector(selector):
if "." in selector and "@" in selector:
parts = selector.split('.')
tag = parts[0]
selector_part = parts[1]
if "@" in selector_part:
num, at_text = selector_part.split('@', 1)
if ":" in num:
num, tag_after_colon = num.split(':', 1)
num = f"{num}@{tag_after_colon}"
if num.replace("-", "").replace(".", "").isdigit():
num = "1" if num == "0" else num # 处理小数点后面是0的情况
if num.startswith("-"):
num = num[1:]
return f"{tag}:nth-last-child({num})@{at_text}"
else:
return f"{tag}:nth-child({num})@{at_text}"
return selector

# 处理列表类型的 JSON 数据
if isinstance(json_data, list):
for item in json_data:
replace_selectors(item)
return

# 遍历字典类型的 JSON 数据,查找并替换选择器
for key, value in json_data.items():
if isinstance(value, str):
if "@" in value:
value = replace_selector(value)
json_data[key] = value
elif isinstance(value, dict):
replace_selectors(value)
elif isinstance(value, list):
for item in value:
if isinstance(item, dict):
replace_selectors(item)

# 增加替换规则,当"ruleExplore": []时,替换为"ruleExplore": "##"
if "ruleExplore" in json_data and not json_data["ruleExplore"]:
json_data["ruleExplore"] = "##"

if __name__ == "__main__":
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
json_url = request.form['json_url']
response = requests.get(json_url)
json_data = response.json()
replace_selectors(json_data)

# 提取文件名,并保存 JSON 内容到文件
file_name = json_url.split('/')[-1]
json_dir = os.path.join(os.path.dirname(__file__), 'json')
if not os.path.exists(json_dir):
os.makedirs(json_dir)

json_path = os.path.join(json_dir, file_name)
with open(json_path, 'w', encoding='utf-8') as file:
json.dump(json_data, file, indent=4, ensure_ascii=False)

# 生成下载链接
download_link = url_for('download', file_name=file_name)

return render_template('result.html', json_data=json_data, download_link=download_link)
return render_template('form.html')

@app.route('/json/<path:file_name>', methods=['GET'])
def download(file_name):
json_dir = os.path.join(os.path.dirname(__file__), 'json')
file_path = os.path.join(json_dir, file_name)
return send_from_directory(json_dir, file_name, as_attachment=True)


app.run(host='0.0.0.0', port=5000, debug=True)

4.2 我甚至还写了个 docker 版本的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 使用python3环境作为基础镜像
FROM python:3

# 设置工作目录
WORKDIR /app

# 安装git,用于从GitHub下载代码
#RUN apt-get update && apt-get install -y git

# 从GitHub下载代码
RUN git clone https://ghproxy.com/https://github.com/wangrui1573/booksource_transIOS.git /app

# 切换到代码目录
WORKDIR /app

# 安装python依赖
RUN pip install --no-cache-dir -r requirements.txt

# 将容器5000端口映射到主机的5000端口
EXPOSE 5000

# 启动Python应用程序
CMD ["python", "api/conv_book_web.py"]


# docker run -d -p 5000:5000 booksource_transios

源代码:https://github.com/wangrui1573/booksource_transIOS