好好住抓图记录

好好住抓图记录

月光魔力鸭

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


感谢支持!

赞赏支持
提交评论
评论信息 (请文明评论)
暂无评论,快来快来写想法...
推荐
在通过axios读取页面的时候,经常会碰到gbk的编码,如果不进行转化的话,在获取信息或读取上都会很麻烦。
分享一个自动抓取静态站资源的小工具,可以在抓取某个静态站点的时候方便很多,尤其是如果页面比较多的话,会很难受,而且会自动将资源进行归类,如果一个页面一个页面的保存的话,那就比较费劲了。
从豆瓣转到网易云后,发现了不少好听的歌曲,然鹅..当我想把这些歌拿下来扔车上听的时候发现竟然不允许下载..能听不能下?这不科学,作为一名程序猿,必然要迎难而上啊.
经常会遇到需要系统重启后自动执行的一些任务,在windows 上可以将对应的程序打包成service 然后自启动即可
产品版本更新的时候经常会有一些数据库的差异,如果版本管理好的话,一步一步升级即可.. 但是如果好久没更新的话,还是有很多不确定的,只能挨着比对表和字段。比对了一次就烦了,写了这么一个工具,查询差异表和字段并给出sql语句。
最近由于系统需要一些数据进行测试,但是正常的流程都是下载pdf ,打印pdf,然后通过涂写答题卡,将涂写的扫描上传..太麻烦了,想做成简单点,通过程序直接生成..卡在了pdf转图片上,今天抽空找了下库,通过gm可以将pdf转为图片,起码第一步已经实现了,后边的涂学号之前已经做过了。
尝试下使用nodejs下开源图像识别库来识别图像状态。
从上面那篇文章过来的,这里分享下nodejs对文件夹以及子文件进行批量删除的实现。