近期发现一个还不错的3D图标库(https://www.thiings.co/things)
图标偏写实风格,都是png格式,也便于在其他项目中引用,看项目的介绍,有1900个图标,都是偏日常生活物品,可以考虑下载下来,打印给崽做干预训练。
官网提供了下载全部的功能,但下载的时候提示需要29美元,且不支持我仅有的国内的银行卡及在线支付方式,又不得不让我望而却步了。
所以不得不祭出国内程序员的大杀器:白嫖。以下便是白嫖全过程。
页面分析
经过对页面源码的分析,发现该网页为使用 Next 开发的单页应用,页面使用 Webpack 打包,滚动页面过程中没有发起异步请求,那相关的文件路径应该是打包在工程里的。
经浏览一个图标,发现如下规律:可通过如下URL下载到原始图片:https://lftz25oez4aqbxpq.public.blob.vercel-storage.com/image-UnbACooeDKA5ggSg36Zi8JizoYINpv.png,经过进一步分析,URL 中的 UnbACooeDKA5ggSg36Zi8JizoYINpv 对应的图片的ID。
经过进一步分析,我们在源码底部找到了相关资源定义的json数据,经过清洗得到如下精简后的json格式的定义数据:
{
"currentPage": "COLLECTION",
"shouldShuffle": true,
"rootPath": "/things",
"canDownload": true,
"categories": ["Everyday", "Nature", "Technology", "Sponsors"],
"forceLength": 1900,
"items": [
{
"id": "amphitheater",
"name": "Amphitheater",
"categories": ["places \u0026 structures", "entertainment", "urban"],
"fileId": "oS7mN2q1OPFw7HHZGO30XoFqCjQJba",
"shareUrl": "https://www.thiings.co/things/amphitheater"
},
{
"id": "sofa",
"name": "Sofa",
"categories": ["everyday life", "furniture", "seating"],
"fileId": "cRuokpRSq9ekpqqbJA3w5Tg4DWOyLv",
"shareUrl": "https://www.thiings.co/things/sofa"
},
{
"id": "toaster",
"name": "Toaster",
"categories": ["everyday life", "appliance", "kitchen"],
"fileId": "UnbACooeDKA5ggSg36Zi8JizoYINpv",
"shareUrl": "https://www.thiings.co/things/toaster"
},
{
"id": "bookshelf",
"name": "Bookshelf",
"categories": ["everyday life", "furniture", "storage"],
"fileId": "4r2tNFAParX1lIOupxBEg3fPYP7GuT",
"shareUrl": "https://www.thiings.co/things/bookshelf"
}
]
}
由此我们可以遍历json中的items数组获取所有资源,然后拼凑图片URL并逐个下载对应的png原图即可。
资源下载
这种数据爬取方面的操作,还是采用我最熟练的 magic-api 来实现,主要分两个步骤:
1、解析json文件并将文件入库
为了便于后续资源利用,我们将上面的json数据保存到MySQL中,建表语句如下:
-- zzl_resources.things_icons definition
CREATE TABLE `things_icons` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增ID',
`oid` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '原始id',
`name` varchar(200) COLLATE utf8mb4_general_ci NOT NULL COMMENT '名称',
`categories` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT 'json数组',
`categories_str` varchar(500) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '便于按类别搜索的字符串',
`file_id` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '文件Id',
`share_url` varchar(200) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '详情URL',
`note` varchar(2000) COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '详情页的描述信息',
`add_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='https://www.thiings.co/things 网站的图标爬取专用';
由于json数据较大,我们将数据保存在磁盘文件中(things_resources.json),然后读取解析保存入库,代码如下:
import cn.hutool.core.io.FileUtil
import cn.hutool.core.date.DateTime
import cn.hutool.core.date.DateUtil
import org.jsoup.helper.DataUtil
import cn.hutool.json.JSONUtil
import cn.hutool.core.util.ObjectUtil
import cn.hutool.core.util.StrUtil
import log
var timer = DateUtil.timer();
var jsonStr = FileUtil.readString("/cosmos/apps/uploads/things_resources.json","UTF-8");
var things = JSONUtil.parseArray(jsonStr)
// log.info('jsonStr:' + jsonStr)
for (thingItem in things) {
var categoriesStr = ''
if (thingItem.categories && thingItem.categories.length > 0) {
categoriesStr = "," + thingItem.categories.join(',') + ","
}
if (!thingItem.shareUrl) {
log.info('跳过入库:' + thingItem.fileId)
continue
}
var data = {
oid: thingItem.id,
name: thingItem.name,
categories: JSONUtil.toJsonStr(thingItem.categories),
categoriesStr: categoriesStr,
fileId: thingItem.fileId,
shareUrl: thingItem.shareUrl
}
log.info(JSONUtil.toJsonStr(data))
db['ZR'].table('things_icons').insert(data)
}
log.info(`Cost Time: ${timer.intervalPretty()}.`);
return '操作成功'
2、下载相关的原图
数据保存入库后,我们可以遍历记录,然后下载到指定目录,一下是下载代码:
import cn.hutool.http.HttpUtil
import cn.hutool.core.io.FileUtil
import cn.hutool.core.date.DateTime
import cn.hutool.core.date.DateUtil
import org.jsoup.helper.DataUtil
import cn.hutool.json.JSONUtil
import log
import http
var list = db['ZR'].table('things_icons').select()
var index = 0
var size = list.size()
var timer = DateUtil.timer();
for ( item in list) {
var fileId = item.fileId
var url = `https://lftz25oez4aqbxpq.public.blob.vercel-storage.com/image-${fileId}.png`
try {
HttpUtil.downloadFileFromUrl(url, `/cosmos/apps/uploads/things-icons/${item.name}__${fileId}.png`)
} catch(e) {
log.info(`something error:${item.fileId}`)
}
index++
log.info(`index/size:${index}/${size}`)
}
log.info(`Cost Time: ${timer.intervalPretty()}.`);
return 'success'
执行该方法后,耗时 1小时46分。
下载了 1908 张图片,共计 2.78G
通过对下载的图片进行统计,发现所有png图片均为1024*1024的分辨率,每张图片基本上都在1M以上,只要不涉及商用版权纠纷的场景,这样规范的图片可以直接用在很多地方。
评论 (0)