好好住抓图记录

好好住抓图记录

月光魔力鸭

2019-09-11 08:17 阅读 790 喜欢 0 好好住爬图

根据好好住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啦。

转载请注明出处: https://chrunlee.cn/article/haohaozhu-spider-img.html


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
碰到个小需求,本来实现挺简单的,用的electron,开发模式下各种顺畅...半个小时就搞定了,结果倒在了electron打包上..这个坑我应该跳进来了好多次了..
在我们做运维或者小工具的时候,总会有些需要提醒的事情,比如服务器宕机或者天气提醒,但是发email又会不够及时或者可能会忽略,那么短信就是一个不错的选择了
使用nodejs 连接mysql数据库还是很简单的,有现成的模块可以直接调用。下面介绍下 mysql 的调用
今天写文章,突然发现自己常用的素材站换成了webp格式的图片.. 可惜本站还没准备加这个支持,所以准备加个webp转jpg的小功能,继续使用啦。
最近有接触到针对二维码进行识别的功能,然后对图片进行位置纠正、二维码扫描,并将数据进行整理。以下是通过nodejs做的,相对简单一些,没有太过严格,识别率也不是很高大约80%左右
这事其实很简单,就是调用adb几个命令而已.. 主要是有时候想用的时候总感觉差点啥,东拼西凑才弄出来,这里记录下,哪怕就是贴个地址的,也比记在脑子里强。
由于国家的行政区划每年都有变化,所以经常需要更新最新的数据,这里提供一个nodejs版本mysql数据存储的抓取示例。
最近有客户提出了这么一个需求:微信dat文件在解码后的图片无法按照时间进行排序。 是的,解码后的文件的时间都是解码的时间,由于软件比较多,当时没做自动更新,所以在这里做一个小工具,可以将对应的解码后的图片的时间修改为微信dat文件对应的时间