JS监听事件型爬虫

最近开始研究网页参数的JS加密,但是大型网站的JS文件过于繁杂,不适合新手上路,于是乎找了几个简单的网页来学习学习。

首先要和大家聊的是监听事件型爬虫(推荐FireFox浏览器)。简单介绍一下JS事件监听:

JavaScript之事件概念和监听事件

1、事件的概念:

JavaScript使我们有能力创建动态页面,网页中的每一个元素都可以产生某些触发JavaScript函数的事件。我们可以认为事件是可以被JavaScript侦测到的一种行为。

2、事件流:

事件流主要分为冒泡型事件和捕获型事件。IE浏览器目前只支持冒泡型事件,而支持标准DOM的浏览器比如火狐、Chrome等两者都支持。

3、使用返回值改变HTML元素的默认行为:

  HTML元素大都包含了自己的默认行为,例如:超链接、提交按钮等。我们可以通过在绑定事件中加上"return false"来阻止它的默认行为。

4、通用性的事件监听方法:

(1)绑定HTML元素属性:

<input type="button" value="clickMe" onclick="check(this)">

(2)绑定DOM对象属性:document.getElementById("xxx").onclick=test;

(https://www.cnblogs.com/dorra/p/7349747.html)

目标网站:http://ac.scmor.com/

第一次写js类的爬虫,断点调试过程写详细些。

鼠标点击现在访问时,会前往另一个网页。用火狐浏览器打开,元素定位到“现在访问”,可以看到下图:网页链接没有出现在源代码中,相反在<a>标签末尾有一个event;这代表当点击“现在访问”这个事件发生时,会被监听并做出相应的反应。

点击“event”,可以看到一个函数onclick(event),在这个函数里,还有一个visit()函数;这表示当点击“现在访问”发生时,会引发onclick(event)的发生,从而引发visit()函数。

全局搜索(ctrl+shift+f)搜索visit()可以看到下图有一个function visit(url);这就是我们要找的函数啦。(这一步开始使用谷歌浏览器)

来分析一下这个函数:它的变量是url,也就是上图中visit('QSQ7XggEHBUhXDxYLwIFHwh4ZRkwXFI0Pw4jGj5ZXlI=')的QSQ7XggEHBUhXDxYLwIFHwh4ZRkwXFI0Pw4jGj5ZXlI=

给它打断点:

点击“现在访问”:此时url=QSQ7XggEHBUhXDxYLwIFHwh4ZRkwXFI0Pw4jGj5ZXlI=

不断点击(step over next function call),当走完strdecode()函数后,url更新为要访问的页面。下一步就是找到这个函数并分析。

找到的strdecode()函数如下:此时

string='QSQ7XggEHBUhXDxYLwIFHwh4ZRkwXFI0Pw4jGj5ZXlI='

再经过base64decode以后变成了一段乱码:

重新打一次断点:经过base64decode(code)后,返回需要的Url;至此所有的断点调试就完成了。

这是base64decode函数的代码,里面有一个base64DecodeChars的变量,在函数里是没有定义的,因此后期自己加上。

function base64decode(str) {
    var c1, c2, c3, c4;
    var i, len, out;
    len = str.length;
    i = 0;
    out = "";
    while (i < len) {
        do {
            c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff]
        } while (i < len && c1 == -1);
        if (c1 == -1) break;
        do {
            c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff]
        } while (i < len && c2 == -1);
        if (c2 == -1) break;
        out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
        do {
            c3 = str.charCodeAt(i++) & 0xff;
            if (c3 == 61) return out;
            c3 = base64DecodeChars[c3]
        } while (i < len && c3 == -1);
        if (c3 == -1) break;
        out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
        do {
            c4 = str.charCodeAt(i++) & 0xff;
            if (c4 == 61) return out;
            c4 = base64DecodeChars[c4]
        } while (i < len && c4 == -1);
        if (c4 == -1) break;
        out += String.fromCharCode(((c3 & 0x03) << 6) | c4)
    }
    return out
}

还有一个问题,最开始visit()的自变量在哪里呢?网页源代码中都有的噢。一共16个镜像对应16个变量。

找到了所有需要的js代码,然后用python还原???不用自己找虐,python提供一个execjs的库,可以直接调用js文件。一共15行代码就可以获得所需的网址啦。

if __name__ == '__main__':
    url='http://ac.scmor.com/'
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'
    }
    html=requests.get(url,headers=headers).text
    soup=BeautifulSoup(html,'lxml')
    infs=soup.find('head').find_all('script',type='text/javascript')
    infs=re.findall(r'autourl(.*?);',str(infs))
    node = execjs.get()
    file = '谷歌学术镜像.js'
    ctx = node.compile(open(file, encoding='utf-8').read())
    for inf in infs:
        data=inf.split('=',1)[1][2:-1]
        js='strdecode("{}") '.format(data)
        print(ctx.eval(js))

最后结果如下:

代码以及Js文件上传到GitHub(https://github.com/zuobangbang/javascript-decode/tree/master/google);觉得不错就star/fork下;有兴趣可以自己做一遍。

原文发布于微信公众号 - Python数据科学(PyDataScience)

原文发表时间:2019-01-03

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券