Python爬虫-js案例-全球能源监测站电厂数据

网址 http://globalenergyobservatory.org/ ,获取其全球电厂数据

以三门峡水电站为例,网站能提供的数据非常丰富,这里我只关心基本信息如名字,摘要信息,经纬度,电厂定位精度,边界信息
全球能量监测站-三门峡水电站
其中名字,摘要信息,经纬度,电厂定位精度等都可以在通过requests.get的方式直接获取,边界经纬度信息无法直接获取

分析

  1. 经验告诉我,边界信息可能在页面中以html标签属性的方式给出,然后在地图上画出边界信息,检查发现没有
  2. 查看网络请求,看是否有其他链接,提供边界数据,发现也没有,麻烦,两个地方都没有,有点懵逼-.-!!!
  3. 在地图上打点或者画边界信息,一定需要传入经纬度,既然在源码和请求连接中均未发现,那数据就是被隐式给出了,此时我想到的是看下是不是js处理了边界数据
  4. 溜达了一圈,js太长,且由于暂无搜索关键字可以快速帮我定位关键代码,导致速度很慢,有点烦躁,突然灵光一闪,既然没找到边界数据来源,那Google地图在画边界信息的时候总得传入边界数据吧?稍微研究了下Google Maps API ,其添加多边形的方法是 google.maps.Polygon(),于是乎搜索了一波google.maps.Polygon关键字,一不小心发现了今天的主角 全球能量监测站-googlemapapi_polygon
  5. 分析图片中的js片段可知,多边形边界信息来自 path: google.maps.geometry.encoding.decodePath(Points),其中 Points = document.getElementById(‘Points’+overlaysCount).value;,行吧,我去源码看看属性id 含"Points"的标签,如图
    全球能量监测站-points标签
    好吧,此前并未注意到该标签,此时js中Points = “{hqsEqnqfTwDuCoB}b@lAaExD]z@dPm@Fp@bLbGq@h@jAkGjD”,要想获取path,还需知道google.maps.geometry.encoding.decodePath函数,此时走断点调试
    整理出关键js
// var Points = document.getElementById('Points'+overlaysCount).value;
var Points = '{hqsEqnqfTwDuCoB}b@lAaExD]z@dPm@Fp@bLbGq@h@jAkGjD';
var Points = 'ksoxDwtqfTiT~PwD}JpBaCjClEnBkAzFmEo@_FrAoD';
L = function(a) {
    return a ? a.length: 0
};

Xc = function(a) {
    if (! (a instanceof Vc)) throw a;
    Uc(a.name + ": " + a.message)
};

Kc = function(a, b, c) {
    null != b && (a = Math.max(a, b));
    null != c && (a = Math.min(a, c));
    return a
};

Lc = function(a, b, c) {
    c -= b;
    return ((a - b) % c + c) % c + b
};

R = function(a, b, c) {
	console.log('---['+a+','+b+']---')
    if (a && (void 0 !== a.lat || void 0 !== a.lng)) try {
        sd(a),
        console.log(sd(a))
        b = a.lng,
        a = a.lat,
        c = !1
    } catch(d) {
        Xc(d)
    }
    a -= 0;
    b -= 0;
    c || (a = Kc(a, -90, 90), 180 != b && (b = Lc(b, -180, 180)));

    // console.log(a);
    // console.log(b);
    console.log('['+a+','+b+']')
    this.lat = function() {
        return a
    };
    this.lng = function() {
        return b
    }
};

decodePath = function(a) {
    for (var b = L(a), c = Array(Math.floor(a.length / 2)), d = 0, e = 0, f = 0, g = 0; d < b; ++g) {
        var h = 1,
        k = 0;
        do {
            var l = a.charCodeAt(d++) - 63 - 1;
            h += l << k;
            k += 5
        } while ( 31 <= l );
        e += h & 1 ? ~ (h >> 1) : h >> 1;
        h = 1;
        k = 0;
        do l = a.charCodeAt(d++) - 63 - 1,
        h += l << k,
        k += 5;
        while (31 <= l);
        f += h & 1 ? ~ (h >> 1) : h >> 1;
        c[g] = new R(1E-5 * e, 1E-5 * f, !0)
        // console.log('['+c[g].lat+','+c[g].lng+']')
    }
    c.length = g;
    // console.log(c) ;
    return c;
};

decodePath(Points);

执行该段js代码,输出经纬度信息如下
全球能量监测站-js执行结果

将这组经纬度一次在地图上打点,发现就是我们要的边界信息,此时破解完成!我们把它转成python版本

def descrypt_bounds(encrypt_str):
    d ,e , f , g = 0,0,0,0
    results = []
    for m in range(0,len(encrypt_str)):
        h,k = 1,0
        l = 0
        if d>=len(encrypt_str):
            break
        while 1:
            l = ord(encrypt_str[d]) - 63 - 1
            h += l << k
            k += 5
            d += 1
            if l<31:
                break

        temp =  ~ (h >> 1) if h & 1 else h >> 1
        e += temp

        h, k = 1, 0
        while 1:
            # print('dddddddd------', d)
            l = ord(encrypt_str[d]) - 63 - 1
            h += l << k
            k += 5
            d += 1
            # print('LLLLL:' + str(l))
            if l < 31:
                break

        temp = ~ (h >> 1) if h & 1 else h >> 1
        f += temp
        results.append([1E-5 * e,1E-5 * f])
    print(results)
    return  results

总结

  1. 调试js如果有比较巧的思路,能起到事半功倍的效果,有机会把js调试的一些方法和经验分享给大家
  2. 该网站整理了不少电厂类数据,数据维度相当丰富
  3. js调试很需要耐心!!!!

文档仅作学习和记录使用,请不要用于商业和违法用途,如有侵权,请告知删除。

猜你喜欢

转载自blog.csdn.net/SpiritedAway1106/article/details/95079456