新手小白如何快速獲取數(shù)據(jù)集
大家好,我是非著名Copy攻城獅胡琦,很久很久沒有動手寫點(diǎn)什么了,今天又有幸參加了 ModelArts 開發(fā)者社區(qū)組織的關(guān)于 AIGallery 的會議,AIGallery ,這是一個開放的平臺,在這里可以學(xué)習(xí)和分享算法、模型、數(shù)據(jù)、Notebook、文章、課程、論文……從AI小白到大神的成長之路(PS:可惜不才沒有上道,依舊是小白)。因此,希望在這里也能記錄下自己的成長之路,給大家?guī)砦乙詾楹糜玫臄?shù)據(jù)集生成之道,獻(xiàn)丑了!
前言
【FBI Warning:本方法目前只局限于從某度圖片獲取數(shù)據(jù)且非常適合圖像分類但不一定適用于實(shí)際應(yīng)用場景!!!】 前端時間想體驗(yàn)一下零基礎(chǔ)體驗(yàn)美食分類的AI應(yīng)用開發(fā),需要一個美食數(shù)據(jù)集,因此找了一些工具來獲取我想要的美食圖片,最終選定了 Github 上某個前端項(xiàng)目來批量下載指定關(guān)鍵字的圖片到本地。本文將詳細(xì)介紹那一百來行的代碼究竟有何“魔力”能夠助我一臂之力從某度下載大量的圖片。
代碼
目錄結(jié)構(gòu)
從目錄結(jié)構(gòu)來看,出去 Git 忽略配置文件 .gitignore、自述說明文檔 README.md 以及前端 npm 包依賴文件 package.json,核心文件也就兩個:baidu-img.js 用來訪問網(wǎng)頁并輸入關(guān)鍵字獲取圖片列表, imgload.js 用來下載圖片。我們查看 package.json 就能看到所需的 npm 包,這里的 npm 包可以理解為引入外部的依賴,讓我們的程序能夠快速獲得某種能力。package.json 如下:
{ "name": "spider", "version": "1.0.0", "description": "", "main": "req.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start":"node baidu-img" }, "keywords": [], "author": "", "license": "ISC", "dependencies": { "axios": "^0.19.2", "bufferutil": "^4.0.1", "cheerio": "^1.0.0-rc.3", "optimist": "^0.6.1", "puppeteer": "^5.2.1", "utf-8-validate": "^5.0.2" } }
dependencies 字段中定義了我們依賴的外部包,其中axios是前端項(xiàng)目中常用的基于Promise的HTTP客戶端,可用于瀏覽器和node.js,我們可以理解為以前 JQuey 中的 Ajax ;Puppeteer是谷歌開源的可調(diào)用高級API來通過DevTools協(xié)議控制無頭Chrome或Chromium的工具,這里用來提供一個無頭的瀏覽器進(jìn)行訪問指定網(wǎng)頁。至于其它的依賴包,代碼中并沒有用到,我們可以先忽略。接下來,看看代碼實(shí)現(xiàn)。
關(guān)鍵代碼
baidu-img.js
// 引入依賴 const puppeteer = require('puppeteer') const url = require('url') const path = require('path') const imgLoad = require('./imgload') // 定義訪問地址 const httpUrl = 'https://image.baidu.com/' var argv = require('optimist').argv; // 入?yún)?let options = { word:argv.word || '圖片', num:argv.num || 60, dir:argv.dir || 'images', delay:argv.delay || 600 } ;( async function(){ // Puppeteer 配置 let config = { headless:true,//無界面操作 ,false表示有界面 defaultViewport:{ width:820, height:1000, }, } // 運(yùn)行瀏覽器 let browser = await puppeteer.launch(config) // 打開 https://image.baidu.com/ let page = await browser.newPage() await page.goto(httpUrl) // 定位到輸入框并輸入關(guān)鍵字,點(diǎn)擊搜索 // 這里的 #kw .s_newBtn .main_img 都是頁面的元素 await page.focus('#kw') await page.keyboard.sendCharacter(options.word);//搜索詞 await page.click('.s_newBtn') //頁面搜索跳轉(zhuǎn) 執(zhí)行的邏輯 page.on('load',async ()=>{ console.warn('正在為你檢索【'+options.word+'】圖片請耐心等待...'); await page.evaluate((options)=>{ ///獲取當(dāng)前窗口高度 處理懶加載 let height = document.body.offsetHeight let timer = setInterval(()=>{ //窗口每次滾動當(dāng)前窗口的2倍 height=height*2 window.scrollTo(0,height); },2000) window.onscroll=function(){ let arrs = document.querySelectorAll('.main_img') //符合指定圖片數(shù) if(arrs.length>=options.num){ clearInterval(timer) console.log(`為你搜索到${arrs.length}張【${options.word}】相關(guān)的圖片\n準(zhǔn)備下載(${options.num})張`); } } },options) }) await page.on('console',async msg=>{ console.log(msg.text()); //提取圖片的src let res = await page.$$eval('.main_img',eles=>eles.map((e=>e.getAttribute('src')))) res.length = options.num res.forEach(async (item,i)=>{ // 下載圖片 await page.waitFor(options.delay*i)//延遲執(zhí)行 await imgLoad(item,options.dir) }) // 關(guān)閉瀏覽器 await browser.close() }) })()
以上的代碼,類似于人的操作:打開網(wǎng)頁-->輸入關(guān)鍵字-->點(diǎn)擊搜索-->瀏覽結(jié)果并下載。
imgload.js
const path = require('path') const fs = require('fs') const http = require('http') const https = require('https') const {promisify} = require('util') const writeFile = promisify(fs.writeFile); module.exports = async (src,dir)=>{ if(/\.(jpg|png|jpeg|gif)$/.test(src)){ await urlToImg(src,dir) } else { await base64ToImg(src,dir) } } const urlToImg = (url,dir)=>{ const mod = /^https:/.test(url)?https:http const ext = path.extname(url) fs.mkdir(dir,function(err){ if(!err){ console.log('成功創(chuàng)建目錄') } }) const file = path.join(dir, `${Date.now()}${ext}`) //請求圖片路徑下載圖片 mod.get(url,res=>{ res.pipe(fs.createWriteStream(file)) .on('finish',()=>{ console.log(file+' download successful'); }) }) } //base64-download const base64ToImg = async function(base64Str,dir){ //data:image/jpg;base64,/fdsgfsdgdfghdfdfh try{ const matches = base64Str.match(/^data:(.+?);base64,(.+)$/) const ext = matches[1].split('/')[1].replace('jpeg','jpg')//獲取后綴 fs.mkdir(dir,function(err){ if(!err){ console.log('成功創(chuàng)建'+dir+'目錄') } }) const file = path.join(dir, `${Date.now()}.${ext}`) const content = matches[2] await writeFile(file,content,'base64') console.log(file+' download successful'); }catch(e){ console.log(e); } }
運(yùn)行
按照前端的慣例,一般需要安裝一下 NodeJS ,好比業(yè)界流傳的“無Node不前端”的調(diào)侃,NodeJS 是 JavaScript 的運(yùn)行時,提供了服務(wù)端的能力。我們把代碼下載下來之后,先安裝 NodeJS,接著運(yùn)行npm install安裝依賴,再運(yùn)行node?.\baidu-img.js?--word=反光衣?--num=1000?--dir=./dataset/反光衣?--delay=200就能夠下載1000張反光衣的圖片了,當(dāng)然,往往理想是豐滿的,現(xiàn)實(shí)往往需要我們再打磨打磨。
好像就這么簡單,分享到此結(jié)束……
最后,如果您沒有數(shù)據(jù)集,可以來 AIGallery 逛一逛,說不定就有合適的數(shù)據(jù)集,甚至可以直接用來訓(xùn)練!我在 huaweicloud.ai ,期待您的參與!
AI開發(fā)平臺ModelArts JavaScript web前端
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時內(nèi)刪除侵權(quán)內(nèi)容。