摘要:做了什么一個用于爬取上妹子圖片的爬蟲。于是觀察瀏覽器正常瀏覽行為。在請求頭中設(shè)置和。解決該問題斷線繼續(xù)下載圖片下載個文件時,經(jīng)常斷線。應(yīng)該是網(wǎng)站的飯爬蟲機(jī)制起了作用,暫時無法解決。于是在保存圖片時會先判斷圖片是否存在。
做了什么
一個用于爬取www.nvshens.com上妹子圖片的爬蟲。如有侵權(quán),馬上關(guān)閉
一張張下實(shí)在太麻煩了
0. node -v >= 7.6 1. git clone https://github.com/laihaibo/beauty-spider.git 2. npm i 3. npm run start (爬取相冊圖片鏈接,并保存為json) 4. npm run calc (獲取爬取的相冊數(shù)和文件數(shù)) 5. npm run download (下載圖片文件)update against反爬蟲
圖片下載完之后會發(fā)現(xiàn)變成了盜鏈圖片。于是觀察瀏覽器正常瀏覽行為。在請求頭中設(shè)置referer, accept和user-agent。解決該問題
request.get(url).set({ "Referer": "https://www.google.com", "Accept": "image/webp,image/*,*/*;q=0.8", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3091.0 Safari/537.36" }).end((err, res) => {})斷線繼續(xù)下載
圖片下載700個文件時,經(jīng)常斷線。應(yīng)該是網(wǎng)站的飯爬蟲機(jī)制起了作用,暫時無法解決。重新下載時理應(yīng)跳過已經(jīng)下載的文件。于是在保存圖片時會先判斷圖片是否存在。
let isExit = fs.existsSync(path); if (!isExit) { saveOne(...args) }獲取理應(yīng)下載的相冊數(shù)和文件數(shù)
let data = JSON.parse(fs.readFileSync(path)); let count = data.reduce((prev, cur) => prev + cur.imgList.length, 0); console.log(`共${data.length}個相冊,共${count}張圖片`);步驟
引入所需的庫
const fs = require("fs"); const mkdirp = require("mkdirp"); const cheerio = require("cheerio"); const request = require("superagent"); require("superagent-charset")(request);
頁面分析,配置config文件
分析相冊地址,以韓國這個標(biāo)簽為例,首頁為https://www.nvshens.com/gallery/hanguo/, 第二頁為https://www.nvshens.com/gallery/hanguo/2.html
const config = { current: "hanguo", allTags: { rougan: `https://www.nvshens.com/gallery/rougan/`, hanguo: "https://www.nvshens.com/gallery/hanguo/" } }
封裝獲取指定url的html內(nèi)容函數(shù)
//該網(wǎng)站編碼為utf-8 const getHtml = url => { return new Promise((resolve, reject) => { request.get(url).charset("utf-8").end((err, res) => { err ? reject(err) : resolve(cheerio.load(res.text)); }) }) }
獲取本分類下所有相冊的標(biāo)簽
/** * @param {string} startUrl 標(biāo)簽首頁的url地址 */ const getAlbums = (startUrl) => { return new Promise((resolve, reject) => { let albums = []; // 用于保存該標(biāo)簽的所有相冊信息 let getQuery = async startUrl => { try { let $ = await getHtml(startUrl); let pages = $("#listdiv .pagesYY a").length; // 獲取頁數(shù) for (let i = 1; i <= pages; i++) { let pageUrl = `${startUrl + i}.html` // 設(shè)置每頁的url let $ = await getHtml(pageUrl); // 動態(tài)設(shè)置pages的值 let compare = $("#listdiv .pagesYY a").map(function (i, el) { return parseInt($(this).text(), 0); }).get().filter(x => x > 0); pages = conmpare.length < 2 ? pages : compare.reduce((prev, cur) => Math.max(prev, cur)); $(".galleryli_title a").each(function () { albums.push({ title: $(this).text(), url: `https://www.nvshens.com${$(this).attr("href")}`, imgList: [], id: parseInt($(this).attr("href").split("/")[2], 10) }) }) } resolve(albums); // 返回相冊信息 } catch (error) { console.log(error); } } getQuery(startUrl); }) }
獲取所有相冊的圖片信息
/** * @param {string} startUrl 該相冊首頁的url地址 */ const getImgList = (startUrl) => { return new Promise((resolve, reject) => { let albums = []; // 存儲本相冊的所有圖片信息 let getQuery = async startUrl => { try { let $ = await getHtml(startUrl); let pages = $("#pages a").length; for (let i = 1; i <= pages; i++) { let pageUrl = `${startUrl + i}.html` let $ = await getHtml(pageUrl); $("#hgallery img").each(function () { let url = $(this).attr("src"); //圖片地址 let fileName = url.split("/").pop(); //文件名 let id = parseInt(fileName.split(".")[0], 10); //id albums.push({ url, fileName, id }) }) } resolve(albums); // 返回本相冊的所有圖片信息 } catch (error) { console.log(error); } } getQuery(startUrl); }) }
保存相冊信息
/** * @param {string} path 保存數(shù)據(jù)的路徑 * @param {array} albums 相冊信息數(shù)組 */ const saveData = (path, albums) => { fs.writeFile(path, JSON.stringify(albums, null, " "), function (err) { err ? console.log(err) : console.log("Data saved"); }); }
保存圖片
/** 12. @param {string} title 圖片所在文件夾名 13. @param {string} url 圖片url 14. @param {string} fileName 圖片名 15. @param {array} imgList 單個相冊的圖片信息 */ // 保存一張圖片 const saveOne = (title, url, fileName) => { return new Promise((resolve, reject) => { let path = `./img/${currentImgType}/${title}/${fileName}`; request.get(url).end((err, res) => { if (err) { console.log(`Error: ${err} in getting ${url}`) } fs.writeFile(path, res.body, function (err) { if (err) console.log(`Error: ${err} in downloading ${url}`) }); resolve(); }) }) } //保存一個相冊下的多張圖片 const saveImg = ({title,imgList}) => { // 創(chuàng)建文件夾 mkdirp(`./img/${currentImgType}/${title}`, function (err) { if (err) { console.log(`Error: ${err} in makedir ${title}`); } }); let getQuery = async() => { try { for (let {url,fileName} of imgList) { await saveOne(title, url, fileName); } } catch (error) { console.log(error); } } // 打印下載一個相冊所需時間 console.time(`download ${title}...`) getQuery(); console.timeEnd(`download ${title}...`) }
執(zhí)行爬蟲
const doSpider = async() => { try { // 獲取相冊信息 let albums = await getAlbums(allTags[current]); // 獲取每張圖片信息 for (let album of albums) { let imgList = await getImgList(album.url); album.imgList = imgList; } // 保存json let jsonPath = `./data`; mkdirp(jsonPath, function (err) { if (err) { console.log(`Error: ${err} in makedir of Json`); } }); saveData(`${jsonPath}/${currentImgType}.json`, albums); // 保存圖片 for (let value of albums) { saveImg(value) } } catch (error) { console.log(error); } }心得體會
有些坑如果不踩過一遍是不會吐血的,比如cheerio的操作和fs的操作
just do it
感謝本文有參考nieheyong的HanhandeSpider和其他的爬蟲文章,得到很多啟發(fā)
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/84186.html
摘要:然而,可用數(shù)據(jù)集的規(guī)模卻沒有成比例地擴(kuò)大。這還說明無監(jiān)督表征學(xué)習(xí),以及半監(jiān)督表征學(xué)習(xí)方法有良好的前景。例如,對于對象探測得分,單個模型目前可以實(shí)現(xiàn),高于此前的。此外,構(gòu)建包含圖片的數(shù)據(jù)集并不是最終目標(biāo)。 都說深度學(xué)習(xí)的興起和大數(shù)據(jù)息息相關(guān),那么是不是數(shù)據(jù)集越大,訓(xùn)練出的圖像識別算法準(zhǔn)確率就越高呢?Google的研究人員用3億張圖的內(nèi)部數(shù)據(jù)集做了實(shí)驗,然后寫了篇論文。他們指出,在深度模型中,視...
摘要:前端每周清單第期微服務(wù)實(shí)踐,與,組件技巧,攻防作者王下邀月熊編輯徐川前端每周清單專注前端領(lǐng)域內(nèi)容,以對外文資料的搜集為主,幫助開發(fā)者了解一周前端熱點(diǎn)分為新聞熱點(diǎn)開發(fā)教程工程實(shí)踐深度閱讀開源項目巔峰人生等欄目。 前端每周清單第 26 期:Node.js 微服務(wù)實(shí)踐,Vue.js 與 GraphQL,Angular 組件技巧,HeadlessChrome 攻防 作者:王下邀月熊 編輯:徐川...
摘要:接下來我看看一下函數(shù)我們先按照分支走為讀取是里的對象,饒了這大的一個圈子,那么接下來一起來看一看對你的輸入配置做了怎么樣的處理吧 打開webpeck-cli下的convert-argv.js文件 // 定義options為空數(shù)組 const options = []; // webpack -d 檢查 -d指令 if (argv.d) { //... } ...
摘要:從社區(qū)和過往的經(jīng)驗而言異步編程的難題已經(jīng)基本解決無論是通過事件還是通過模式或者流程控制庫。本章主要介紹了主流的幾種異步編程解決方案這是目前中主要使用的方案。最后因為人們總是習(xí)慣性地以線性的方式進(jìn)行思考以致異步編程相對較為難以掌握。 前言 如果你想要深入學(xué)習(xí)Node,那你不能錯過《深入淺出Node.js》這本書,它從不同的視角介紹了 Node 內(nèi)在的特點(diǎn)和結(jié)構(gòu)。由首章Node 介紹為索引...
閱讀 2577·2021-10-25 09:45
閱讀 1239·2021-10-14 09:43
閱讀 2297·2021-09-22 15:23
閱讀 1519·2021-09-22 14:58
閱讀 1934·2019-08-30 15:54
閱讀 3539·2019-08-30 13:00
閱讀 1354·2019-08-29 18:44
閱讀 1571·2019-08-29 16:59