为了准备 LoRA 数据集,我第一次用爬虫批量下图
最近想自己试一下训练 LoRA,但卡得很现实:数据集不够。
一开始我还想着手动下,后来下了十几张就受不了了。恰好这段时间在学Python,发现这事如果不借助代码,基本做不下去。所以这篇先记一下这段时间正经使用Python时的思路变化:从想逆接口,到逆不出来,再到最后老老实实开浏览器,模拟手动翻页,在 DOM 里拿图像地址去下载。
1. 起因很简单:想训 LoRA,但手动下载太慢了
这段时间找了一个底模,稳定性很好。工作上业务需要多风格,只能去训练 LoRA。
但训练这件事,说到底还是要先准备数据集。这个问题一落到手上,我最先碰到的不是训练参数,而是最基础的一件事:
图不够,而且手动下载太慢。
刚开始我还觉得这事应该不复杂。
无非就是:
- 打开网页
- 一张张翻
- 一张张保存
但真试了以后,很快就发现不对。
因为一旦数量上来,手动操作会特别机械,前面少量搞一搞还行,真要为训练准备一批像样的数据,这种方式效率太差了。
所以问题很快就变成了:
能不能直接把网页里的图批量拿下来?
正好试试这段时间学的Python,这也算是我第一次带着很明确的目标去碰“爬虫”这个东西。
2. 我一开始想走的路,是先逆接口
最开始我对爬虫的想象还挺直接的。
我会觉得,既然网页上的图片最后总得从某个接口回来,那最理想的做法当然是:
- 找到接口
- 把请求参数抄下来
- 直接请求数据
- 再把图片地址取出来下载
这个思路看起来很对,而且也比较“程序员”。
所以我在家那几天,主要就是在看网页请求,想试着把它逆出来。
那时候我做的事情基本就是这些:
- 打开开发者工具看 Network
- 看翻页时发了哪些请求
- 看返回体里有没有图片地址
- 看请求参数是怎么带的
- 看 headers、分页参数、时间戳这些东西有没有规律
我一开始还挺有期待,觉得只要把接口盯住,后面就顺了。
结果实际试下来,并没有我想得那么简单。
3. 接口我不是完全没看到,是“看到了也没真正拿下来”
这个地方我得先记一下,不然后面容易把事情说得太轻松。
我不是完全没看到请求。
问题是:看见请求,不等于你就能顺利把它复现出来。
我当时碰到的难点主要在这几类:
- 请求参数不止明面上的分页信息
- 有些值看起来像是动态生成的
- 页面行为和接口触发不完全是一一对应的
- 有些请求就算抄出来了,自己发也不一定拿到同样的结果
说白了就是,我能感觉到这条路是对的,但以我现在的水平,还没法把它稳定复现出来。
这个阶段挺消耗人的,因为它会让你反复停在这种状态里:
- 感觉快摸到了
- 但就是差一口气
- 改一下参数还是不行
- 再试一下请求头也不行
我后来慢慢接受了一个现实:
这条路我不是完全学不会,而是至少在现在,不适合作为我先解决问题的第一条路。
这点对我其实挺重要。
因为它让我第一次比较明确地意识到:
技术上“最优雅”的方案,不一定是当前最适合我的方案。
如果我一直卡在逆接口这件事上,业务需求就要超时了,别人都在等着我。
4. 接口走不通以后,我开始换思路:先别追求优雅,先把图拿下来
我后来给自己换了一个目标:
先别管是不是最漂亮的爬法,先把这件事做成。
既然网页本来就能正常展示图片,说明至少有两件事已经成立:
- 浏览器能把页面翻下去
- 页面里最终能出现我要的图片地址
那我就不一定非得先把底层接口完全啃下来。
我完全可以换一种更笨、但更接近人工操作的办法:
- 直接开一个浏览器
- 让脚本去模拟翻页
- 每翻一页,就从 DOM 里找图片地址
- 找到地址以后再去下载
这个思路一出来,整件事一下就落地多了。
因为它把问题从“我能不能先逆明白接口”换成了:
- 我能不能让页面自动翻
- 我能不能从页面元素里把地址取出来
- 我能不能把这些地址批量存下来
这三件事,至少都比逆接口更贴近我当时能做的范围。
5. 这次我第一次真正开始理解:DOM 不是前端专属词,它对爬虫也很关键
以前我对 DOM 这个词的印象,其实更多还是“网页结构”。
但这次开始碰这种浏览器模拟方案以后,我才比较实际地感觉到:
DOM 对爬虫来说也非常重要。
因为我最后不是去接口里直接拿数据,而是去页面上找已经渲染出来的内容。
这件事一旦落到代码里,核心就变成了:
- 这一页的图片元素在哪
- 图片地址是在
src里,还是在别的属性里 - 翻页之后,DOM 什么时候更新
- 什么时候取值最稳
我不再只是“看网页”,而是开始把网页当成一棵可以被脚本读取的结构树。
这个理解对我帮助挺大。
因为它把我前面学 Python 时那些零散概念,第一次往一个真实场景里接上了。
6. 后面我的做法其实不复杂:模拟手动翻页,然后从 DOM 把地址拿出来
我最后走通的方案,核心逻辑其实挺朴素的。
第一步:启动浏览器
先让程序把目标网页打开,而不是自己手动一点点操作。
第二步:模拟人工翻页
这一点很关键。
因为我要的图片不是一开始就全在第一页里,所以程序不能只打开一次页面就结束,而是得像人一样往后翻。
第三步:等页面内容更新
翻页以后不能立刻拿数据,不然很容易拿到旧内容或者空内容。
所以这一步我当时也开始慢慢意识到:
- 浏览器自动化不是“点了就算完成”
- 页面有没有真正更新,要等
- 有时候还得判断某个元素是不是已经出现
第四步:从 DOM 里取图像地址
这一层才是真正开始拿数据。
我当时的重点不是复杂解析,而是先把这几件事确认清楚:
- 图片标签到底在哪
- 地址是不是已经出现在属性里
- 一页里能取多少张
- 有没有重复
第五步:把地址下载下来
拿到地址以后,后面就简单很多了。
这一步至少比前面的“逆接口”阶段踏实,因为地址已经是实打实能用的结果了。
整个方案看起来不高级,但很适合我当时的状态。
因为它绕开了我暂时还啃不动的地方,先让我把事情做成了。
7. 这件事对我最大的提醒是:先做成,比一开始就追求最优方案更重要
如果只从“技术洁癖”的角度看,这次的方案肯定不是最优雅的。
最优雅的路径,还是应该把接口逆明白,直接请求数据。
但问题是,当时的我还没有那个能力稳定做到。
如果一直死磕那条路,很可能最后什么都没落下。
这次让我比较有感触的一点就是:
解决问题的时候,先判断自己当前能打哪一层。
我现在把这件事记成两个层次:
第一层:理想方案
- 直接逆接口
- 参数规律摸清
- 批量请求数据
- 结构更清晰,效率也更高
第二层:当前可做方案
- 开浏览器
- 模拟翻页
- 从 DOM 里取地址
- 先把数据集下回来
这次我最后选的是第二层。
不是因为第二层更高级,而是因为它对当时的我来说更可执行。
我现在越来越觉得,这种判断其实很重要。
8. 这篇顺手记几个我这次真正碰到的新东西
这次虽然只是为了搞数据集,但它确实让我第一次比较认真地碰到了几样以前只是听过的东西:
1)浏览器自动化
以前我会把脚本理解成“直接请求接口”。这次才发现,浏览器本身也能被程序驱动。
2)DOM 抓取
以前知道 DOM 是网页结构,这次开始把它当成数据来源看。
3)等待和时机
翻页以后不是立刻就能拿值,页面更新时机本身就是问题的一部分。
4)重复数据处理
翻页抓图时,如果不处理重复,最后很容易把同一批图反复下回来。
5)先把问题做成
这次不是最漂亮的方案,但它让我第一次有了一个完整闭环:
- 有目标
- 有失败尝试
- 有方案切换
- 最后把结果拿到
9. 先记一个阶段结论
这次为了准备 LoRA 数据集去碰爬虫,我现在先记下几个结论:
- 逆接口和真正复现接口,是两回事
- 在当前能力不够的时候,浏览器模拟 + DOM 抓取是一个很实用的兜底方案
- 页面上的结果,本身也可以当数据源,不一定非得先从底层接口拿
- 爬虫不只是“发请求”,有时候更像是在自动执行一套人工操作
- 先把事做成,再回头优化方案,这个顺序对我现在更合适
这篇先记到这里。
这次虽然只是为了下图,但我已经明显感觉到,Python 到了这里,它已经慢慢变成一个能帮我解决实际问题的工具了。
