好好住抓图记录

好好住抓图记录

BUG集散地

2019-09-11 08:17 阅读 22 喜欢 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


如果对你有用的话,请赏给作者一个馒头吧 ...或帮点下页面底部的广告,感谢!!

赞赏支持
提交评论
评论信息(请文明评论)
暂无评论,快来快来写想法...
推荐
记录下在linux环境下安装phantomjs 的步骤,防止遗忘...
写文章总会需要一些素材,但是好多素材都是收费或有限制的,还是我要求不高,在千库网看了下还不错,有各签到还送VIP,于是就有了想法....
记录下通过nodejs调用imagemagick 的时候发现的一个错误,command failed -- crop .
学习爬虫的时候突然有想到想做一个音乐播放小站,可以给自己或朋友听,但是音乐哪里来呢??想到自己常听的豆瓣FM,就越发的想把这些音乐都拿下来,因此有了下文通过豆瓣FM批量抓取上万首音乐,目前已经3W+。
当我们想实现一个自己的库或模块后,发布的话,需要发布到npm上才能下载。以下是具体步骤
互联网应用经常需要存储用户上传的图片,比如facebook相册。 facebook目前存储了2600亿张照片,总大小为20PB,每张照片约为80KB。用户每周新增照片数量为10亿。(总大小60TB),平均每秒新增3500张照片(3500次写请求),读操作峰值可以达到每秒百万次
在使用marked来做md解析的时候,部分解析规则可能并不是很如意,比如说,我在md中写了a标签,但是这些标签都是在当前页面替换的,而我想要的是新打开窗口。
因为自己的记录笔记的应用是有道云,又想着把有道云跟自己的小网站联通起来,所以查找了有道云的,然后实现了nodejs版本的sdk.