好好住抓图记录

简介: 最近家里正在装修,实在是不知道怎么做,之前看好好住APP上有不少设计的图,部分还挺好看。。就去看了下有没有WEB端,结果还真有,就有了下文,我抓了几万张图片,然后根据关键字进行分类,从里面找心仪的设计。

根据好好住WEB端的一些请求记录,发现,可以可以直接通过URL API进行调取,获得里面的记录,就能直接拿到数据了。

如果只是API其实是最简单的了,这里还记录下,主要是抓了没十几页..IP就被封了,下面还加上拿代理IP并自动切换的故事。

代理IP - 拿的齐云代理

//获取齐云代理的数据

let cheerio = require('cheerio');

let axios = require('axios');


let getHtml = function(pageIndex){
    let url = `http://www.qydaili.com/free/?action=china&page=${pageIndex}` ;
    return axios.get(url)
    .then(rs=>{return rs.data});
}

let getTable = function(html){

    let $ = cheerio.load(html);
    let $container = $('.container');
    let $trs = $container.find('tbody tr');
    let arr = [];
    $trs.each((i,item)=>{
        let ip = $(item).find('td[data-title="IP"]').text().replace('IP','');
        let port = $(item).find('td[data-title="PORT"]').text().replace('PORT','');
        let type = $(item).find('td[data-title="类型"]').text().replace('类型','');
        arr.push({
            ip : ip,
            port : port,
            type : type,
            isHttps : type == 'HTTPS' ? true : false,
            str : ip+':'+port
        });
    })
    return arr;
}


module.exports = async function(pagesize){
    let html = await getHtml(pagesize);
    let arr = getTable(html);
    return arr;
}

提供页码数,然后获得页面上的代理IP信息,返回即可,后续使用httphttps 由客户端决定。

好好住抓图

API

API 地址: https://www.haohaozhu.cn/f/y/api/Share/AllPhotoInPc
请求参数:

keyword : '',//关键词
page : page,//页数
time : +new Date()//请求时间

代码

//好好住.. 抓图,为装修找灵感

let axios = require('axios');
let qs = require('querystring');
let fs = require('fs');
let async = require('async');

let url = 'https://www.haohaozhu.cn/f/y/api/Share/AllPhotoInPc';

let page = 1;
let map = {};
let ippool = [];//ip proxy pool

const tunnel = require('tunnel')



let getIpsFn = require('./getIps');
let currentIpsIndex = 0;
let getIps = async function(){
    currentIpsIndex ++ ;
    let arr =await  getIpsFn(currentIpsIndex);
    let httpsArr = [];
    arr.forEach(item=>{
        if(item.isHttps){
            httpsArr.push(item);
        }
    })
    if(httpsArr.length == 0){
        httpsArr = await getIps();
    }
    console.table(httpsArr);
    return httpsArr;
}

//cip : 是否切换IP
let getPicData = function(page,ipItem){
    console.log(`当前使用的代理:${ipItem ? ipItem.str : '无'}`);
    const tunnelProxy = ipItem ? tunnel.httpsOverHttp({
        proxy: {
            host: ipItem.ip,
            port: ipItem.port,
        },
    }) : null;
    return axios({
        url : url,
        method : 'post',
        data : qs.stringify({
            keyword : '',
            page : page,
            time : +new Date()
        }),
        proxy : false,
        httpsAgent : tunnelProxy,
        timeout : 10000,
        headers : {
        
            'accept': 'application/json, text/plain, */*',
            'accept-encoding': 'gzip, deflate, br',
            'accept-language': 'en,zh-CN;q=0.9,zh;q=0.8',
            'cache-control': 'no-cache',
            // 'content-length': '25',
            'content-type': 'application/x-www-form-urlencoded',
            'origin': 'https://www.haohaozhu.cn',
            'pragma': 'no-cache',
            'referer': 'https://www.haohaozhu.cn/community/discover',
            'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
        }

    })
    .then(rs=>{
        console.log(`获取到正常数据`)
        // console.log(rs);
        return rs.data;
    })
    .catch(err=>{
        //如果报错,全部认为超时,换IP
        console.log('这里的错误???')
        console.log(err.message);
        return {code : 2};
    })

}
//抓取单个图片并进行保存
function fetchImg(item){
    return new Promise((resolve,reject)=>{
        if(!fs.existsSync('./'+item.folder+'/'+item.name)){
            axios({
                url : item.url,
                method : 'get',
                timeout : 5000,
                responseType : 'stream',
                onDownloadProgress : function(er){
                    console.log(er);
                },
                headers : {
                    'referer': 'https://www.haohaozhu.cn/community/discover',
                    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'
                }
            })
            .then(rs=>{
                console.log('抓取数据中...准备写入['+item.name+']')
                let imgPath = './'+item.folder+'/'+item.name;
                const ws = fs.createWriteStream(imgPath);
                //当前图片写入完毕
                var t = setTimeout(function(){
                    console.log(`超时未写入,删除文件...继续`)
                    fs.unlinkSync(imgPath);
                    resolve();
                },15000);//
                ws.on('close',()=>{
                    clearInterval(t);
                    resolve();
                });
                ws.on('error',(err)=>{
                    resolve();
                })

                rs.data.pipe(ws);
            })
            .catch(err=>{
                console.log(err.message);
                resolve();
            })
        }else{
            console.log(`已经存在文件:${item.name}`);
            resolve();
        }
    });
}
function waitFor(time){
    return new Promise((resolve,reject)=>{
        setTimeout(function(){
            resolve();
        },time);
    });
}
//
;(async function start ( page,cip ){
    try{
        console.log(`启动抓取,当前页面:${page}`)
        let data = await getPicData(page,cip);
        if(null != data && undefined != data && data.data.rows.length == 0 && data.code == 1){
            console.log(`已经没有数据可抓......-0---OVER`)
            page = 1;
            await start(page,cip);
        }else if(null == data || undefined == data || null == data.data || undefined == data.data || data.code == 2){//IP proxy
            //切换ip 代理池。
            if(ippool.length == 0){
                ippool = await getIps();
            }
            let ipItem = ippool.splice(0,1);
            await start(page,ipItem[0]);
        }else{
            //json 存储起来
            fs.writeFileSync('./json/'+page+'.json',JSON.stringify(data));
            var rows = data.data.rows;
            let imgList = [];
            rows.forEach(item=>{
                let photo = item.photo,
                    info = photo.photo_info,
                    tag = info.admin_tag,
                    list = info.image_list;
                var imgArr = list.map(img=>{
                    return {
                        folder : 'img',
                        id : img.pic_id,
                        url : img.ori_pic_url,
                        name : tag+'_'+img.pic_id+'.png'
                    };
                });
                imgArr.push({
                    folder : 'avatar',
                    url : photo.user_info.big_avatar,
                    name : photo.user_info.uid+'.png'
                });
                imgList = imgList.concat(imgArr);
            })

            console.log(`当前页面共有图片:${imgList.length}张`)
            //循环下载...
            for(const item of imgList){
                // let item = imgList[i];
                if(item.id && map[item.id]){
                    console.log(`已存在该图片`)
                }else{
                    await fetchImg(item);    
                }
            } 
            console.log(` 当前页面抓取结束`)
            //开始继续下一个,直接没有数据再进行结束
            page++;
            //等待10分钟后,继续执行
            await start(page,cip);
        }
    }catch(e){
        if(ippool.length == 0){
            ippool = await getIps();
        }
        let ipItem = ippool.splice(0,1);
        await start(page,ipItem[0]);
        //有报错?不怕死。重新来
    }
})(1);

因为伴随着数据后,主要就是图片的存储而已,所以整体上来说,难度很小。

axios 代理

代理使用了模块tunnel.

const tunnelProxy = ipItem ? tunnel.httpsOverHttp({
        proxy: {
            host: ipItem.ip,
            port: ipItem.port,
        },
    }) : null;
axios({
        url : url,
        method : 'post',
        proxy : false,
        httpsAgent : tunnelProxy,
        timeout : 10000
});

也不知道是代理的问题还是代码的问题,总之,代码运行一段时间后...就卡那了,还没发现是哪里导致的,初步猜测可能是好好住服务器给挂住请求了..


暂时先这样,需求并不是很惊喜,拿到图然后根据tag进行分类,找了下自己心水的设计就OK啦。

相关文章
|
JSON NoSQL Redis
逆转时间,起死回生——程序报错崩溃后,如何倒回到崩溃的位置?
逆转时间,起死回生——程序报错崩溃后,如何倒回到崩溃的位置?
112 0
复制一个5G文件只需要两秒,全网最牛方法!
复制一个5G文件只需要两秒,全网最牛方法!
|
存储 缓存 监控
腾讯三面:进程写文件过程中,进程崩溃了,文件数据会丢吗?
腾讯三面:进程写文件过程中,进程崩溃了,文件数据会丢吗?
206 0
腾讯三面:进程写文件过程中,进程崩溃了,文件数据会丢吗?
|
存储 机器学习/深度学习 监控
我是傻x,被迫看了 1 天源码,千万别学我!
大家好,我是零一,之前一直很忙,业余时间的输入和输出都 24k铝合金人眼可见 得下降,这不最近上海疫情严重么,算了一下居家办公也已经将近 1个月了,这才有些许时间学习,所以最近也是一直在鼓捣点新东西,不为别的,主要是想再多输入一些新的知识
188 0
我是傻x,被迫看了 1 天源码,千万别学我!
|
芯片
程序人生 - 手上总有静电该怎么处理?
程序人生 - 手上总有静电该怎么处理?
161 0
程序人生 - 手上总有静电该怎么处理?
|
存储 前端开发 JavaScript
一不小心文件上传服务hang住了?
一不小心文件上传服务hang住了?
301 0
|
人工智能 达摩院 前端开发
想爱的人,想去的地方,一秒钟都不想等了!
万物复苏,终于复工。上周,橙子在内网上向阿里同学发起提问:2020我们拥抱变变变化,但无论发生什么2020你都想「做成」的事是什么?
300 0
想爱的人,想去的地方,一秒钟都不想等了!
|
SQL 关系型数据库 MySQL
妈妈再也不用担心我把数据弄丢了
数据是现代大小厂的重要资产,保护和恢复数据成为了重要的技能, 最近几年,常有一些无良程序员删库跑路的情况,不仅给所在企业更是给自己造成重大的损失。 另外,即使不是故意的情况下,也会因为疏忽造成数据误操作,是一件及麻烦又头疼的事情……
156 0
|
架构师
需求又变了,要不要怼回去?
产品经理要系统性思考问题
370 0
|
Web App开发 SQL Java
艾伟_转载:一次挂死(hang)的处理过程及经验
前言:        CPU占用率低,内存还有许多空余,但网站无法响应,这就是网站挂死,通常也叫做hang。这种情况对于我这样既是CEO,又是CTO,还兼职扫地洗碗的个人站长来说根本就是家常便饭。以下是一次处理hang的经验及总结,前后用了一个月,不仅涉及程序排查,数据库优化,还有硬件升级的苦恼。
1680 0