yandex 图片自动下载
yandex 图片自动下载命令行程序
一个在 yandex 上搜索图片并下载到本地的 node cli 程序.
使用帮助:
$0 <搜索关键词> [-t=超时(默认 1000)] [-r 是否替换下载(默认 false)]
示例:
$0 shop # 搜索 shop 并下载
$0 shop -t=0 # 不使用超时
$0 shop -t=0 -r # 覆盖重名文件
一个群友让做的程序, ¥100. 需求就是使用 yandex 搜索图片, 并自动下载到本地.
分析
- 打开 https://yandex.com/images/search?text=shop
- 查看 images/search? 请求, p={当前页数}
- 返回结果 blocks[0].params.lastPage 是最大页数
- 返回结果中所有 img_url={原图地址}
win 下简单的命令行交互
这里用批处理实现, 其实 node 中也可以做交互的.
C:.
│ yandex 图片自动下载.bat
│
└─lib
node_modules
index.js
node.exe
yandex 图片自动下载.bat 文件内容
color f0 && chcp 936 && cls && @echo off
title yandex 图片自动下载
mode con cols=120 lines=30
:down
set /p keyword=输入关键词开始下载:
.\lib\node.exe .\lib\index.js "%keyword%"
echo ==========================
echo 全部下载完成
goto :down
源码
index.js
const fs = require('fs')
const url = require('url')
const path = require('path')
const fly = require('flyio')
const text = process.argv[2]
if(text === undefined) {
console.log(`
使用帮助:
$0 <搜索关键词> [-t=超时(默认 10000)] [-r 是否替换下载(默认 false)]
示例:
$0 shop # 搜索 shop 并下载
$0 shop -t=0 # 不使用超时
$0 shop -t=0 -r # 覆盖重名文件
`)
return
}
const argv = parseArgv()
const userConfig = {
text, // 用户搜索的关键词
timeout: argv['-t'] === undefined ? 10000 : Number(argv['-t']), // 设置超时时间, 默认 10 秒
replace: argv['-r'] || false, // 是否替换下载, 默认否
}
const config = userConfig
fly.config.timeout = config.timeout
const downHistoryFile = `${process.cwd()}/download.txt`
fs.writeFileSync(downHistoryFile, '')
const downDir = `${process.cwd()}/download`
new Promise(async () => {
let text = userConfig.text
let {urls: lastUrls = [], lastPage = 0} = (await getImgUrls({text}).catch(err => console.log('err', err))) || {}
if(lastPage === 0) {
console.log('没有搜索结果, 你可以更换关键词重试')
return
}
for (let p = 0; p < lastPage; p++) {
let curPage = p + 1
let urls = []
if(curPage === 1) {
urls = lastUrls
} else {
let getRes = await getImgUrls({text, p: curPage}).catch(err => console.log('err', err))
urls = (getRes || {}).urls || [] // 获取页数
}
urls = [...new Set(urls)] // 去除重复的 url
// urls = urls.slice(0, 3)
const paseUrls = []
urls.map(item => {
const {pathname, href} = url.parse(item)
let {base, ext, name} = path.parse(pathname);
ext = ext || '.jpg' // 如果没有扩展名时, 默认给定为 jpg
// let fullName = paseUrls.find(item => item.fullName === base) // 如果保存文件名重复, 则添加时间戳处理
// ? `${name}_${uuid()}_${ext}`
// : base
// let fullName = `${name}_${uuid()}_${ext}`
let fullName = `${name || uuid()}${ext}`
paseUrls.push({
name,
fullName,
href,
})
})
console.log(`正在下载第 ${curPage}/${lastPage} 页`)
await Promise.all(paseUrls.map(item => download(item.href, item.fullName))).finally(async () => {
console.log(`第 ${curPage}/${lastPage} 页下载完成`)
})
}
})
function hasFile(filePath) {
return fs.existsSync(filePath)
}
function parseArgv() {
return process.argv.slice(2).reduce((acc, arg) => {
let [k, v = true] = arg.split('=')
acc[k] = v
return acc
}, {})
}
async function getImgUrls(arg = {}) {
arg = {
text: 'shop',
p: 1,
...arg,
}
return new Promise((resolve, reject) => {
console.log(`正在查找图片, 关键词: ${arg.text}, 页: ${arg.p}`)
let api = `https://yandex.com/images/search?format=json&request=%7B%22blocks%22%3A%5B%7B%22block%22%3A%22serp-controller%22%2C%22params%22%3A%7B%7D%2C%22version%22%3A2%7D%2C%7B%22block%22%3A%22serp-list_infinite_yes%22%2C%22params%22%3A%7B%22initialPageNum%22%3A0%7D%2C%22version%22%3A2%7D%2C%7B%22block%22%3A%22more_direction_next%22%2C%22params%22%3A%7B%7D%2C%22version%22%3A2%7D%2C%7B%22block%22%3A%22gallery__items%3Aajax%22%2C%22params%22%3A%7B%7D%2C%22version%22%3A2%7D%5D%2C%22bmt%22%3A%7B%22lb%22%3A%22%22%7D%2C%22amt%22%3A%7B%22las%22%3A%22justifier-height%3D1%3Bthumb-underlay%3D1%3Bjustifier-setheight%3D1%3Bfitimages-height%3D1%3Bjustifier-fitincuts%3D1%3Bchunk.219.0%3D1%3Bchunk.169.0%3D1%22%7D%7D&yu=2650822041574437239&p=${arg.p}&text=${encodeURIComponent(arg.text)}&rpt=image&uinfo=sw-1920-sh-1200-ww-905-wh-1045-pd-2-wp-16x10_2560x1600`
// console.log('api', api)
fly.get(api)
.then(res => {
const data = res.data
handleData(data, r => resolve(r))
}).catch(err => {
reject(err)
})
})
}
function execSync(cmd, out = false) {
const child_process = require('child_process')
let str = child_process.execSync(cmd).toString().trim()
out && console.log(str)
return str
}
async function handleData(data, cb) {
try {
const lastPage = data.blocks[0].params.lastPage
const urls = []
data.blocks.forEach(item => {
(item.html.match(/img_url=.*?&/g) || []).forEach(item => {
urls.push(decodeURIComponent((item.match(/img_url=(.*?)&/) || [])[1] || ""))
})
})
cb({
lastPage,
urls,
})
} catch (error) {
console.log('error', error)
cb({
msg: '搜索结果出现错误',
error,
lastPage: 0,
urls: [],
})
}
}
async function download(u, p) {
fs.writeFileSync(downHistoryFile, fs.readFileSync(downHistoryFile) + u + '\r\n')
const savePath = `${downDir}/${p}`
if(!config.replace && hasFile(savePath)) {
console.log(`跳过已下载 ${p}`)
return true
} else {
if(!hasFile(downDir)) {
fs.mkdirSync(downDir)
}
return fly.download(u, savePath)
.then(d => {
console.log(`下载成功: ${p}`)
})
.catch(err => console.log('err', err.message))
}
}
function uuid(sep = '') {
let increment = process.increment === undefined ? (process.increment = 1) : (process.increment = (process.increment + 1))
return `${Date.now()}_${increment}`.replace(/_/g, sep)
}
package.json
{
"name": "getImg",
"version": "1.0.0",
"description": "",
"main": "index.js",
"keywords": [],
"author": "xw",
"dependencies": {
"flyio": "^0.6.14",
"request": "^2.88.0"
},
"license": "ISC"
}
注:
本程序有个小问题, 懒得解决, 看大家能不能发现.
yandex 图片自动下载的更多相关文章
- 【图文详解】python爬虫实战——5分钟做个图片自动下载器
python爬虫实战——图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识,(没看的先去看!!)大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap sho ...
- python爬虫实战——5分钟做个图片自动下载器
python爬虫实战——图片自动下载器 制作爬虫的基本步骤 顺便通过这个小例子,可以掌握一些有关制作爬虫的基本的步骤. 一般来说,制作一个爬虫需要分以下几个步骤: 分析需求(对,需求分析非常重要, ...
- MIT-Adobe FiveK Dataset 图片自动下载
MIT-Adobe FiveK Dataset 图片自动下载 MIT-Adobe FiveK是现在很多做图像增强(image enhancement)与图像修饰(image retouching)方面 ...
- 【Python开发】【神经网络与深度学习】网络爬虫之图片自动下载器
python爬虫实战--图片自动下载器 之前介绍了那么多基本知识[Python爬虫]入门知识(没看的赶紧去看)大家也估计手痒了.想要实际做个小东西来看看,毕竟: talk is cheap show ...
- 如何用Python爬虫实现百度图片自动下载?
Github:https://github.com/nnngu/LearningNotes 制作爬虫的步骤 制作一个爬虫一般分以下几个步骤: 分析需求 分析网页源代码,配合开发者工具 编写正则表达式或 ...
- dedecms复制网上的带有图片的文章,图片不能自动下载到本地的解决方法
dede有时看到比较好的文章需要复制,粘贴到自己的dede后台发布,dede是有图片自动本地化的功能,就是复制过来后自动下载到你的服务器上了,这样省去了你单独去另存图片再上传的过程,尤其是遇到有很多图 ...
- 基于.NetCore开发博客项目 StarBlog - (17) 自动下载文章里的外部图片
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 【壁纸自动换】自动下载、更换壁纸(Bing壁纸)--XinBSBingWallPaper[2.7更新]
XinBSBingWallPaper主要功能: 1.支持自动下载Bing壁纸.Netbian壁纸.美国国家地理杂志图片. 2.自动搜索.下载多国Bing首页壁纸. 3.支持定时自动更换桌面壁纸. 4. ...
- JS图片自动或者手动滚动效果(支持left或者up)
JS图片自动或者手动滚动效果(支持left或者up) JS图片自动或者手动滚动效果 在谈组件之前 来谈谈今天遇到搞笑的事情,今天上午接到一个杭州电话 0571-28001187 即说是杭州人民法院的 ...
随机推荐
- 漏洞利用 Exploit---利用默认口令、IP假冒、应用漏洞
漏洞利用 编辑 讨论 本词条由“科普中国”科学百科词条编写与应用工作项目 审核 . 漏洞利用(英语:Exploit,本意为“利用”)是计算机安全术语,指的是利用程序中的某些漏洞,来得到计算机的控制权( ...
- Pytorch Sampler详解
关于为什么要用Sampler可以阅读一文弄懂Pytorch的DataLoader, DataSet, Sampler之间的关系. 本文我们会从源代码的角度了解Sampler. Sampler 首先需要 ...
- GC线程是不是守护线程
是 线程的话分为守护线程和非守护线程(即用户线程) 只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作; 只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作,守护线程 ...
- JMeter基础【第六篇】JMeter5.1事务、检查点、集合点、思考时间、其余设置等
JMeter5.1事务.检查点.集合点.思考时间.其余设置等
- The Best Open Source Game Engine: In Search Of Perfection
https://www.greatsoftline.com/the-best-open-source-game-engine-in-search-of-perfection/ The game eng ...
- 数据库 = filesystem + transcation + dsl + dslengine
数据库 = filesystem + transcation + dsl + dslParser
- python-hashlib加密
用于加密相关的操作,代替了md5模块和sha模块,主要提供SHA1,SHA224,SHA256,SHA512,MD5算法. 以下是算法示例: #!/usr/bin/env python # -*- c ...
- 顶部选项卡-可左右拖动(webview)示例如何做到tab与webview联动滚动
顶部选项卡-可左右拖动(webview)的示例中,如何做到tab与webview联动滚动,效果类似uc头条一样 ps:自己也不确定有多少了到航头,页面怎么办,到航头从后台获取,页面不可能建N多个.ht ...
- PHP的简单了解
PHP 标识符/关键字/数据类型 标识符:其实标识符就是变量的名称,函数与类的名称也是标识符.PHP中标识符的规则: 1.标识符可以是任意长度的字母.数字.下划线,且不得以数字开头. 2.PHP中标识 ...
- springcloud(三)
雪崩效应 一.为什么需要 Hystrix? 在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用(RPC).为了保证其高可用,单个服务又必须集群部署.由于网络原因或者自身的原因,服 ...