抓取图片

本来是想写个爬虫爬一下天地图的地图图块

结果碰到了一些问题,自己总结一下

1.并发问题

其实这个不是新问题,网上也有很多解决方案,只是一开始写了个循环嵌套循环,1秒钟不到发出了90多个请求

90多个请求有时候会成功 有时候会失败

所以用了async的

async.mapLimit

解决并发问题

2.下载图块失败

本来想把失败的存在数组里全部执行完后,再从失败的数组里再次下载

之后放弃了这个想法,因为失败的还是有可能失败的

而且造成失败的原因有很多,不是单纯的让程序反复重试就可以解决问题

最后还是在生成urls数组的时候访问了一下文件夹里图块有没有成功,如果成功就跳过

3.fs模块的坑

fs.readFile是异步的

fs.readFileSync是同步的

在for循环中用同步的才可以 否则循环结束了 因为异步回调的原因 值取不到

代码如下

var request = require('request');
var fs = require('fs');
var path = require('path');
var async = require("async");



var tileMatrix = 10;
var urls = [];
var errorUrl = [];


for (var tileRow = 140; tileRow < 165; tileRow++) {
    for (var tileCol = 825; tileCol < 870; tileCol++) {
        var url = {
                url:  {
                    url:'http://t0.tianditu.com/img_c/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=c&TILEMATRIX=' + tileMatrix + '&TILEROW=' + tileRow + '&TILECOL=' + tileCol +'&FORMAT=tiles',
                    headers: {
                        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
                    }
                }, 
                m: '' + tileMatrix, 
                r: '' + tileRow, 
                c: '' + tileCol
            }
        if(!fs.existsSync(path.join(__dirname + '/1/map/default/img', '' + url.m,  url.r , url.c + '.jpg'))){
            urls.push(url);
        } else {
            var file = fs.readFileSync(path.join(__dirname + '/1/map/default/img', '' + url.m,  url.r , url.c + '.jpg'));
            if (!file.length) {
                urls.push(url);
            }
        }
        
    }
}




async.mapLimit(urls, 20, async function(url) {
    var res = await new Promise((resolve) => {
        console.log('开始下载' + 'm'+ url.m +'r' + url.r + 'c' + url.c + '.jpg')
        if (!fs.existsSync(path.join(__dirname + '/1/map/default/img', url.m,  url.r)))  fs.mkdirSync(path.join(__dirname + '/1/map/default/img', url.m,  url.r));
        request(url.url).on('error', function(err) {
            errorUrl.push(url);
          }).pipe(fs.createWriteStream(path.join(__dirname + '/1/map/default/img', url.m,  url.r , url.c + '.jpg')).on('close', function(){
            console.log('下载完成' + 'm'+ url.m +'r' + url.r + 'c' + url.c + '.jpg')
            resolve(url);
          }));
    })
    return res;
}, (err, results) => {
    console.log('全部完成')
})

写在最后

爬虫网上有很多别人写好现成的,自己再造一遍轮子就是想踏踏坑

有时间再在github上创建个repo 把这个爬虫完善一下