吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 6512|回复: 82
收起左侧

[Web逆向] 武海笔院书籍的 PDF 下载

  [复制链接]
LoveCode 发表于 2024-6-26 17:47
本帖最后由 LoveCode 于 2024-7-7 17:38 编辑

文武双全天灵根。

泉海碧波映佳人。

书笔怎写羞羞事。

局院深处躺平时。


== 欸~道友留步呀,这么着急走作甚?你还没说这 武海笔院 是何处呢?还有,这什么打油诗?

=> 这,>︿< 哎呀,真是的 ,每次都要这样吗?……(四顾无人,施展好不容易修到大圆满境界的隔音术,再悄悄说道)你把每行诗句的开头,对,就开头第一个字连起来看看。

== 啊?哦~~哦!原来如此!(≧∇≦)ノ 道友着实有心了,不过下次可以不要取奇怪的标题吗?别人看不懂也搜索不到这里呀。

=> 咳咳,我也是没办法,所以只能看谁有缘了。

== 好吧,那这 “文……

=> 住口!不要说下去了,千万不要说出那四个字!!!

== ??(#°Д°)

=> (待到平复心中的惊慌,再运起大圆满境界的传音术)唉……我也不想如此呀,此四字为一灵兽的真名,传闻此灵兽道法通天,在此间(注:此间指逆向星域的web 大陆)不可直呼其名,否则冥冥之中感应到我的存在,仅投下一道视线,我必灰飞烟灭、不得入轮回!

此次也不过是远远瞧见了它的一道分身飞过天边,借用留影石保存画面罢了。

==(⊙o⊙) ……嘶~(倒吸一口凉气)原来如此!多谢道友告知,那我一睹其英姿就走!

=> 别急,给,这是本文结构。

  1. 简述下载书籍的方案(留影之术)
  2. 源代码的获取、程序在本地运行的环境配置
  3. 程序的使用方法
  4. 具体的分析流程(断因果)。此部分现在可以忽略,等到将来网站变动时可供参考

缘起

由于一些不可言说的理由(不能说,就算一直盯着我也不能说),我凑齐五十下品灵石前往 武海笔院 购买书籍。

武海笔院 的书籍有两种阅读方式:在网页端看、下载电子书用它的软件看,都不能带出去,所以我想要将书籍下载下来,选择的方式自然也是:分析网页端,爬取它的图片并生成 PDF。所以此种方式下载的 PDF 是无法复制文字的

想要下载完整的书籍需要先用灵石购买它,也就是获得该书籍的阅读权限

我先去散修城的藏经阁寻找方案(指搜索文章、github),前人几乎都是基于 web端爬取图片、合并成 PDF。仔细分析了他们的实现方案、并结合现在灵兽分身的踪迹(指网站的工作方式),发现这些方案容易和该灵兽分身(浏览器)有牵连,会吸引其本体的注意从而被灭(如封 IP、封账号),就像这样:

image-20240625213526732.png

最后,我于高山之上闭关 1 天另寻他法,且看后文分析。

留影之术

下面让我们先探讨现有的、下载图书的方式,最后说明我的解决方案 —— 留影之术。

# ======= 回忆长廊 =======
        启动

# 当前进度:查看书籍的每一页是怎样的结构

查看网站 HTML 结构,发现每一页的内容由 6 张小图片构成,如下:

image-20240623121839423.png

通过浏览器的抓包分析,找到这 6 张小图片的请求。

image-20240623121422143.png

显而易见地:我们需要爬取这些小图片、合成每一页的图片,最后合并所有的页,得到一个 PDF 文件

现在让我们仔细探讨现有的爬取方式。

模拟请求

不推荐此方式。

经过测试,发现在鼠标滚轮滚动时会触发一个 save 请求(滚动一次就触发一次)。

image-20240623220649132.png

这是在做什么呢?这是在记录我的阅读时长,或者说阅读习惯,具体说明如下:

image-20240623221416276.png

模拟请求的方式有以下缺点:

  • 虽然可以模拟上述的 save 请求,但这需要大量测试是否可行,我的帐号只有一个,所以不能轻易尝试。
  • 考虑账号的安全性,模拟请求所耗费的时间、精力(分析请求、分析参数)以及可能承担的后果都使得我不推荐此方式。

自动化工具

不推荐此方式。

在部分解决方案中(注:此处原本想放一个链接,却发现其牵扯到灵兽的另一分身,不得不用我大圆满境界的打码术去除了)使用的是自动化工具 selenium,并且提到了“那 6 张小图片不能二次访问”,其中一个解决方案是用代码控制鼠标右键点击图片来保存。

自动化方案有以下缺点:

  • 自动化工具是可以被检测的,账号只有一个,我要选稳妥的方式
  • 保存图片的时候用 pyautogui 控制鼠标、键盘,这样就不能在电脑上做其它的事情了。

我的方案:代{过}{滤}理捕获,留影之术

既然小图片只能访问一次,我的想法是通过拦截响应来获取图片。这可以写成浏览器插件的形式,不过考虑到要捕获请求了,最好和浏览器分离开来,所以使用代{过}{滤}理的形式!

没错!完全和浏览器隔开,不沾染因果,此乃留影之术的本质

整个流程如下:

image-20240623223921856.png

当然它的缺点很明显:非常占用资源,因为浏览器会一直发出图片请求、并解析、渲染图片啦

== 可是,(。・・)ノ 要怎么自动翻页呢??!

=> 经过前文的分析,我们要稳妥一点,所以不要自动翻页。

== 啊??那我该怎么办?w(゚Д゚)w

=> 手动翻页呗,难不成自己翻页太快也要封账号?!大家可是都会量子波动速读法的!—— 此法术只有在发动的时候才能记住文字,一旦停止施法,读过的内容就全部忘记了,这也许就是该法术的代价吧。

== 什么鸡肋术法,我就是想自动翻页、自动下载!(○´・д・)ノ

=> ……这样,你给我 100 下品灵石,我帮你翻页,这样对你来说也算是自动的。

== 啊!突然记起来传法殿中是有这么个量子什么阅读法的 ╥﹏╥... 可是我宗门贡献分不够兑换呀

=> 真拿你没办法,既然有缘,再多说道一二。现在你可以用任何方式、只要能让浏览器翻页就行 —— 前端就是这样的,只需要好好翻页就行了,可代{过}{滤}理端要考虑的事情就多了

== 嗯?这个句式好像有点眼熟 (´・ω・`)?

=> 咳咳……我认为比较稳妥的是:编写 JS 脚本实现滚动翻页(是让页面慢慢滚动从而翻页,而不是一页一页地、跳跃式翻页),不使用自动化工具来操作浏览器(不要和分身有任何牵连)。如此,自动翻页既安全、也可以做其他的事情嘛。

== 嗯嗯,然后呢?然后呢?

=> 放心,项目里有自动翻页的脚本啦。不过在我的测试中,自动翻页超过一定次数,会弹出错误信息(把我吓出一身冷汗,我甚至感觉到其本体的视线已经跨越时间与空间,将我钉在了此处,它似乎正看我的过去、我的来历,毕竟在他的眼中,小小练气修士是不敢招惹它的,如果它知道我没有强悍的背景,恐怕……额,好像可以无视警告继续翻页欸,咳咳,稳妥起见,可以暂停一会)。

image-20240625231840243.png

image-20240625231945960.png

重要声明

我并没有测试 “一个账号一天翻完了多本书会不会封账号”(这还要花钱买书测试呢!我也不推荐大家尝试),不过仔细想想,怎么说也是手动翻页的,不应该封号才对呀,除非它强烈抗议用户使用量子波动速读法

== 可是,它都明确说了禁止下载……

=> 咳!这个嘛,尽管放心,我也只是自己用啦,我也不推荐道友将这个拿出去乱搞哈。

最后,重要事情说三遍。

建议一天下载一本书,账号只有一个,要用最稳妥的方式!

建议一天下载一本书,账号只有一个,要用最稳妥的方式!

建议一天下载一本书,账号只有一个,要用最稳妥的方式!


环境配置

此部分是大家拿到源代码、在本地运行之前的配置。

https://github.com/Hosinoharu/WuHaiBiYuan_downloader 获取源代码。

配置 Python 环境

首先需要有 Python 3.11 及以上版本(因为我写代码时用的这个版本,我也没有用低版本的 Python 进行测试)。

# 首先进入到项目所在的目录 WuHaiBiYuan_downloader

# 这里使用的是内置的 venv 模块来创建虚拟环境
# 该虚拟环境保存在当前目录(项目所在目录)下的 .venv 目录中
python -m venv .venv

# 然后启动虚拟环境
.\.venv\Scripts\activate

# 修改该虚拟环境 pip 的下载源,大家也可以用自己常用的那个
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ --site

# 执行以下命令安装依赖包
pip install -r requirements.txt

# 测试核心的代{过}{滤}理软件是否安装正常
mitmdump.exe --version
# 执行上行命令之后会输出以下类似的信息
'''
PS > mitmdump.exe --version
Mitmproxy: 10.3.1
Python:    3.11.4
OpenSSL:   OpenSSL 3.2.2 4 Jun 2024
Platform:  Windows-10-10.0.19045-SP0
'''

# 然后启动代{过}{滤}理程序,开始配置证书
mitmdump.exe

配置浏览器的代{过}{滤}理

不同浏览器的代{过}{滤}理配置方式不同(有些浏览器无法单独配置代{过}{滤}理,只有配置到操作系统上),这个大家自己搜索吧。这里以 Firefox 为例,设置方式如下:

image-20240625161214176.png

image-20240621141131373.png

然后点击 OK 完整代{过}{滤}理设置。

配置代{过}{滤}理证书

访问 http://mitm.it 下载证书。我选择证书只用于浏览器本身。

上述的网址来自于官方文档,具体见 Getting Started (mitmproxy.org) 的说明

image-20240621141448184.png

然后给浏览器安装下载的证书,具体步骤也可以点击上图中的 Show Instructions,下面是截图。

image-20240621141715164.png

image-20240621142642849.png

按下图进行选择,最后点击 OK 完成证书配置。

image-20240621142543088.png

测试整个环境

至此环境配置结束,重新运行以下命令看看是否工作正常。

# -s 指定 py 脚本
# -q 表示 quiet,不输出冗余的信息
mitmdump.exe -s .\test\test_env.py -q

# 然后浏览器访问任意网站查看是否有输出结果

image-20240626122531281.png

结束程序之后记得取消代{过}{滤}理

当结束 mitmdump 代{过}{滤}理之后,记得取消浏览器的代{过}{滤}理设置,不然浏览器无法访问任何网站啦。


使用方法

后文的截图可能和实际所示不同,因为现在(写下这段文字的时刻)修复了几个 bug,或者增加了另外一些功能,由于时间原因(才……才不是偷懒 (~ ̄▽ ̄)~),并没有重新截图与说明,但不影响使用。

测试翻页脚本

将项目中 web_script\web_scroll.js 复制出来,添加到油猴脚本(油猴脚本的安装、使用均省略)。

然后测试翻页脚本功能是否正常(注意,此时浏览器没有上代{过}{滤}理呢),此步骤是检测网站的 HTML 结构是否已经变化

image-20240625163132830.png

默认情况下 3s 向下滚动一次(移动 300px),如果当前页面的 6 张小图片没有加载出来则不进行翻页

  • 如果网络慢,网页端都没有加载到图片就继续往下翻,那就不会再发出图片请求,会缺页。
  • 翻得太快网页端也不会发出图片请求,造成缺页。

不要觉得翻页慢,因为翻页的过程中完全可以用浏览器做其他的事情。“快速下载” 和 “账号” 哪一个重要大家自行判断

=> 强烈建议翻慢一点,真要是用了量子波动速度法……出了什么事我可不负责哈!

== 啊??还好我没有用宗门贡献分兑换这鸡肋术法!

=> 总之,现在只需要考虑怎么翻页翻得像人在看书就行

确认要下载的书籍

确认要下载哪本书籍,将其 id 添加到设置文件 proxy_server\settings.jsonc 中。

这是因为使用代{过}{滤}理的方案进行下载时,我们依然可以使用浏览器,为了避免下载其它无关紧要的书籍,需要提前指定要下载哪本书。

image-20240625163250585.png

如果指定了多本书,自然可以开两个标签页同时下载,因为它们都会经过代{过}{滤}理端。

但是为了账号的安全性,不建议这样做。

下载书籍

在命令行中执行 mitmdump.exe -s  .\proxy_server\main.py -q 启动代{过}{滤}理

  1. 访问书本的阅读页,如 https://武海笔院网址/deep/read/pdf?bid=3199625,程序会自动识别书籍信息、目录信息
  2. 然后点击自动翻页按钮就行了。
  3. 之后可以干其他的事情,只需要让该浏览器标签页运行(但不要最小化)即可。

处理单页下载失败

如果下载过程中某一页没有下载也无妨,可以手动滚动页面再访问一次即可。

image-20240625165304730.png

多次刷新网页、或者不小心关闭了标签页都无妨,代{过}{滤}理端不会重复下载已保存的图片。

image-20240625165309666.png

处理代{过}{滤}理端重启

代{过}{滤}理端中途停掉也无妨,可以重启代{过}{滤}理、然后按照之前步骤翻页即可。

image-20240625165313567.png

注意,当代{过}{滤}理端重新启动时,需要刷新阅读页,因为需要重新获取书籍信息、书签,这两个数据会用于判断书籍是否下载完毕、以及后续生成 PDF。同时重启代{过}{滤}理后,会提示有哪些页数还没有下载。

image-20240626124123504.png

保存为 PDF 文件

首先是书籍所有图片、书签信息保存的目录。

image-20240625170403260.png

image-20240625170744138.png

等到下载完毕,就会自动合成 PDF 保存到 download_book 目录下。

image-20240625220458059.png

如果某些原因导致:在下载完所有图片之后,并没有合并成 PDF ,那么可以执行 utils.py 来手动合并 PDF。

image-20240626144641830.png

运行情况说明

运行过程中资源占用率较大,因为浏览器一直翻页、解析、渲染图片。这也是该方式的缺点了,但是账号安全(前提是不能翻页太快)。

image-20240625181936024.png

最后,我下载的那本书共有 365 页,所有下载的图片共 43.4 MB,生成的 PDF 为 90.4 MB。如果大家想继续压缩大小,可以在设置文件中修改保存的图片质量。

同时下载多本书

为了账号的安全性,不建议多本下载,不过这里还是提一下。

首先要停止当前运行的代{过}{滤}理端,然后添加新的书籍 id

image-20240625165618360.png

然后重新启动代{过}{滤}理,按照之前的步骤就可以下载了。

image-20240625170258088.png


留影分身断因果

此部分记录整个分析过程、相关代码的逻辑解释,将来网站变动大家也能自己解决吧

  • 着重记录核心的思路,不包括如何获取书签、生成 PDF 等(已经有很多文章讲解过了)

也就是说现在可以忽略这部分内容

等到下载失败、程序运行异常(这可能是因为网站发生了变动),就可以看此部分的内容,了解大致的分析过程,再自己进行处理。

== 欸~下次变动再找你不就行了?

=> 不可,我一直在探索一个名为二次元的小世界,其内天然困阵居多,常常被困数十年,所以还是靠大家自己。而且经常更新也会无形间沾染该灵兽分身的因果。


根据之前的留影之术 —— 代{过}{滤}理方案,我们可以直接在代{过}{滤}理端保存那些小图片啦,但是问题来了:不知道这 6 张小图片的排列顺序,怎么拼接成完整的一页??

image-20240623230247197.png

确定小图片的顺序

现在让我们进入 回忆长廊 整理思路。

# ======= 回忆长廊 =======
# 查看书籍的每一页是怎样的结构
        每一页是由 6 个小图片组成的,并且在代{过}{滤}理端可以直接下载它们,但是代{过}{滤}理端不清楚这些小图片的顺序。
    只要确定了顺序就可以合成书籍的一页啦。

# 当前进度:如何确定 6 个小图片的顺序

在代{过}{滤}理端只能看到请求的参数、响应等等,猜测小图片的顺序极大可能藏在这个小图片的请求链接中(不然服务器怎么知道请求的是哪个小图片呢)。

根据文章(此处内容已被大圆满层次的打码术进行删除,可通过必应搜索 武海笔院 jwt 来找到相关文章)确定参数 kjwt 加密方式(此处不做解释,请自行必应搜索。它类似 base64,是一种固定的加密/编码方式),在 jwt在线解密/加密 - JSON中文网 可以进行解密,却没有发现特别明显的特征。

初次展示 k 值.png

好啦!现在无法通过小图片的链接来判断它们的顺序,该怎么办??

哼哼,还好我精神力强大,仔细一扫,发现每次请求 6 张小图片时,会先发送 6 个请求并返回奇怪的数据,没错!就是这个!分析流程如下:

WARNING!请注意!我要起名字了,这都是为了后文便于讨论。

我将这 6 个请求称之为 req_before_split_page。表示的是:在小图片(也就是分割的图片)之前的请求。

2次展示 k 值.png

这些 req_before_split_page(还记得这个名字不) 的返回值也是奇奇怪怪的。

image-20240623134230523.png

好的,现在让我们进入 回忆长廊 整理思路。

# ======= 回忆长廊 =======
# 查看书籍的每一页是怎样的结构
        每一页是由 6 个小图片组成的,并且在代{过}{滤}理端可以直接下载它们,但是代{过}{滤}理端不清楚这些小图片的顺序。
    只要确定了顺序就可以合成书籍的一页啦。

# 当前进度:如何确定 6 个小图片的顺序
        发现在获取 6 个小图片之前有 6 个请求,它们的请求参数中似乎包含了小图片的顺序信息。
    而这些请求的返回值似乎还需要进一步处理才行…………

很好,现在需要确定上述 req_before_split_page 请求的响应值是如何处理的,这就需要通过 hook JSON.parse 来发现细节了。

(function () {

    const deep = 5;

    // 输出堆栈信息,至多向上输出 deep 层堆栈
    // 因为有些网站会封装 JSON.parse 的调用
    function get_caller_location() {
        // stack[0] - Error 字符串
        // stack[1] - 调用 new Error 的位置
        // stack[2] - 调用本函数的位置
        // stack[3] - 上一层的位置,后续应该从此处开始
        const stack = (new Error).stack.split('\n');

        if (stack.length >= 4) {
            return "\t" + stack.slice(3, 3 + deep).join("\n\t");
        }
        return "\t" + stack.join("\n\t");
    }

    // 并未没有处理 .toString() 检测,先这样,够用了
    const parse_proxy = new Proxy(JSON.parse, {
        apply: function (target, thisArg, argumentsList) {
            const result = Reflect.apply(target, thisArg, argumentsList);
            console.log("===> Call JSON.parse\n", get_caller_location(), "\n", JSON.stringify(result));
            return result;
        }
    });

    Object.defineProperty(JSON, "parse", {
        value: parse_proxy,
    });
})();

好啦!现在让我们先刷新网页,等待页面加载完毕之后(排除掉干扰数据),注入上述代码,然后滑动鼠标滚轮,触发后续页面的加载!这样 hook JSON.parse 的结果都是有关于这些图片请求的。如下确实发现了线索!

3次展示 k 值.png

完整的回忆长廊

现在让我们最后一次进入 回忆长廊

# ======= 回忆长廊 =======
# 查看书籍的每一页是怎样的结构
        每一页是由 6 个小图片组成的,并且在代{过}{滤}理端可以直接下载它们,但是代{过}{滤}理端不清楚这些小图片的顺序。
    只要确定了顺序就可以合成书籍的一页啦。

# 如何确定 6 个小图片的顺序
        发现在获取 6 个小图片之前有 6 个请求,它们的请求参数中包含了小图片的顺序信息。
    而这些请求的响应值进行处理之后会用于对应的小图片请求!
    通过建立这 6 个请求与 6 个小图片请求的关系,可以确定小图片的顺序!

# 当前进度:梳理流程

现在,让我们看图吧!

4次展示 k 值.png

5次展示 k 值.png

好啦!只要在代{过}{滤}理端确认了小图片的顺序,就可以拼接成完整的一页,然后保存每一页,最后拼接成 PDF 啦!

未来的变化

网站的反爬必定会变化,只要掌握了这 留影之术、寻找小图片顺序的思路,以后大家也能以不变应万变啦。

不过,如果哪一天它的图书图片改成了这种处理方式(看到这种我转头就走)……嗯……所以万万不能让它的本体注意到我。

image-20240625235730852.png


番外:根据时间戳定位

很多网站在加密时会用到时间戳,那么找到特定时间戳的生成位置,也就非常接近核心加密的位置

在控制台执行如下脚本,它可以记录生成时间戳的位置!

(function () {

    //#region 准备存储相关信息

    function get_caller_location() {
        const stack = (new Error).stack.split('\n');

        if (stack.length >= 4) {
            return "\t" + stack.slice(3, 5).join("\n\t");
        }
        return "\t" + stack.join("\n\t");
    }

    // 封装一个简单的 Map,存储时间戳和生成它的位置
    class TimeStorage {
        constructor() {
            /** @Type Map<string, string> */
            this.storage = new Map();
        }

        /**
         * @Param {string} key key
         * @param {string} value value
         */
        set(key, value) {
            this.storage.set(key, value);
        }

        /** @param {string} key key */
        get(key) {

            if (key.length === 13) {
                const s = this.storage.get(key);
                if (s) {
                    console.log("找到时间戳:\n", s);
                } else {
                    console.log("没有找到时间戳");
                }

                return;
            }

            // 传入的时间戳长度可能不足 13 位,因为部分网站会只保留 10 位 
            // 只好一个一个查找了
            const times = this.storage.keys();
            const location = new Set();
            let is_found = false;

            for (const t of times) {
                if (t.includes(key)) {
                    location.add(this.storage.get(t));
                    is_found = true;
                }
            }

            if (is_found) {
                console.log("匹配到时间戳:\n", [...location].join("\n=====\n"));
            } else {
                console.log("没有找到时间戳");
            }
        }
    }

    const time_storage = new TimeStorage();
    window['time_storage'] = time_storage;

    //#endregion

    //#region hook Date 以及 Date.now

    const date_now = new Proxy(Date.now, {
        apply(target, this_arg, args) {
            let result = Reflect.apply(target, this_arg, args);

            time_storage.set(result.toString(), get_caller_location());

            return result;
        }
    });

    Object.defineProperty(Date, 'now', {
        value: date_now
    });

    const date_proxy = new Proxy(Date, {
        construct(target, argumentsList, newTarget) {
            let result = Reflect.construct(target, argumentsList, newTarget);

            time_storage.set(result.valueOf().toString(), get_caller_location());

            return result;
        }
    });

    Object.defineProperty(window, 'Date', {
        value: date_proxy
    });

    //#endregion

})();

然后使用方式如图:

6次展示 k 值.png


== 不对呀,道友既惧因果之累,避而不宣其真名,却又将分身之迹公诸于众,此举已无形间扰动了因果。或许此刻这丝联系尚显微弱,然岁月流转,看过此文的众人其因果皆与尔等牵连,因果循环,假以时日必然织成无法斩断的因果线。

若该灵兽本尊察觉这莫名其妙的因果之线,定追根溯源,寻得道友踪迹。届时,只怕……{{{(>_<)}}}

=> 不早说,我都已经发出去了!!!(っ °Д °;)っ

== 嘿嘿,莫慌,早年偶得一件先天灵物,虽无断因果之能,却能遮掩因果之迹 —— 毕竟那等存在除非被因果线缠身,否则是不会出手的。

=> 哦?这世间竟有如此玄妙之物,听闻只有深谙命运法则的修士能做到这一点。

== 是的,不过此物一直荒废在储物戒指中,于我无用,如今道友急需,百枚灵石即可转让于道友啦。

=> 如此,便有劳了(嗯?此情此景,怎么感觉是很熟悉的操作)

end

免费评分

参与人数 33威望 +1 吾爱币 +51 热心值 +30 收起 理由
笙若 + 1 + 1 谢谢@Thanks!
pangmaomao + 1 热心回复!
aabbccli + 1 + 1 谢谢@Thanks!
一家之言 + 1 + 1 我很赞同!
zhzzhzzh321 + 1 我很赞同!
wangyou918918 + 1 + 1 道友是个性情中的趣人~
枫倾木葉 + 1 + 1 我很赞同!
某不知名用户 + 3 + 1 谢谢@Thanks!
涛之雨 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
DouhiroKwok + 1 + 1 谢谢@Thanks!
lingyun011 + 1 + 1 热心回复!
kexing + 1 + 1 太厉害了!我看着都费劲
MO0328 + 1 我很赞同!
1lifedo1thing + 1 + 1 我很赞同!
bbaimm + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
henrylong1989 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
抱薪风雪雾 + 1 + 1 谢谢@Thanks!
bpzm1987 + 1 + 1 热心回复!
Cave + 1 + 1 热心回复!
myao + 2 + 1 谢谢@Thanks!
唐小样儿 + 1 + 1 我很赞同!
lastmu + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
piaoyuelu + 1 + 1 我很赞同!
cux666 + 1 谢谢@Thanks!
985csust + 1 热心回复!
x7032360 + 1 + 1 谢谢@Thanks!
Bob5230 + 1 + 1 热心回复!
zhczf + 1 + 1 我很赞同!
hubohang + 1 我很赞同!
vethenc + 1 + 1 清晰!
betterzyh + 1 + 1 透彻!
dingqh + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
setekh + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!

查看全部评分

本帖被以下淘专辑推荐:

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

750101 发表于 2024-6-26 19:22
牛逼,完全看不懂
betterzyh 发表于 2024-6-26 18:56
vethenc 发表于 2024-6-26 19:02
guangyingcuojue 发表于 2024-6-26 19:14
学习了,对我来说有点难
xixicoco 发表于 2024-6-26 19:16
分析的不错啊,优秀文章
hanwuj2012 发表于 2024-6-26 19:23
厉害,感谢分享,这个数据库一号难求啊
st520 发表于 2024-6-26 20:12

感觉很不错!谢谢楼主分享!
52shuqi 发表于 2024-6-26 20:26
老哥这写的很有思路呀,诗作的也很好,不过现在那个网站机制太变态,费号
hubohang 发表于 2024-6-26 21:16
全看不懂
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-22 21:53

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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