js混淆反爬破解学习--爬取OpenLaw

1、前言

  前几天看到了瓜子二手车的广告,突发奇想一想要拿这个网站试试手,可每次都没法成功获取到页面。试了不少次都没有结果以后便去网上搜索方案,才知道原来还有js反爬这种东西(看来我之前选网站的运气都太好了。。。),又发现了一篇js混淆反爬破解的文章,就拿来模仿学习一下。html

学习的文章:JS混淆openlaw反爬破解实践
python

文章做者:谢俊杰浏览器

2、抓包分析

 一、使用火狐自带工具进行抓包,发现一次请求加载了两次html页面,以下;cookie

二、分别查看一下两个html  网络

  首先来看看第一个html;app

  

  根据图片咱们能够发现,这是一个简单的html页面里包含着一大串JavaScript代码,<body>里多是一个招聘邮箱(有兴趣的能够联系试一下。。。国内好像不少网站喜欢在这种地方放招聘信息,我发现好几个了。。。)。ide

  接下来咱们再来看看第二个html信息;工具

  能够看出第二个页面才是咱们想要看到的html页面;因此能够猜想,网页通过第一个页面的跳转才会到达咱们想要的页面,接下来咱们就要弄清楚第一个页面究竟干了些什么。学习

3、分析第一个页面js代码

一、咱们将第一个页面代码截取下来,而且格式化一下(我能够很负责任的告诉大家,我是真的格式化了的);网站

 1 var O01 = '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';  2 function lOO(data) {  3     var OOOlOI = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";  4     var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, enc = '';  5     do {  6         h1 = OOOlOI.indexOf(data.charAt(i++));  7         h2 = OOOlOI.indexOf(data.charAt(i++));  8         h3 = OOOlOI.indexOf(data.charAt(i++));  9         h4 = OOOlOI.indexOf(data.charAt(i++)); 10         bits = h1 << 18 | h2 << 12 | h3 << 6 | h4; 11         o1 = bits >> 16 & 0xff; 12         o2 = bits >> 8 & 0xff; 13         o3 = bits & 0xff; 14         if (h3 == 64) { 15             enc += String.fromCharCode(o1) 16         } else if (h4 == 64) { 17             enc += String.fromCharCode(o1, o2) 18         } else { 19             enc += String.fromCharCode(o1, o2, o3) 20  } 21     } while (i < data.length);return enc 22 } 23 function OOO(string) { 24     var ret = ''
25       , i = 0; 26     for (i = string.length - 1; i >= 0; i--) { 27         ret += string.charAt(i); 28  } 29     return ret; 30 } 31 eval(lOO(OOO(O01))); 32 window.n = "j_token"; 33 eval(function(p, a, c, k, e, d) { 34     e = function(c) { 35         return (c < a ? "" : e(parseInt(c / a))) + ((c = c % a) > 35 ? String.fromCharCode(c + 29) : c.toString(36)) 36  } 37  ; 38     if (!''.replace(/^/, String)) { 39         while (c--) 40             d[e(c)] = k[c] || e(c); 41         k = [function(e) { 42             return d[e] 43  } 44  ]; 45         e = function() { 46             return '\\w+'
47  } 48  ; 49         c = 1; 50  } 51     ;while (c--) 52         if (k[c]) 53             p = p.replace(new RegExp('\\b' + e(c) + '\\b','g'), k[c]); 54     return p; 55 }('1 2$=[\'\\9\\5\\6\\4\\3\\7\\8\'];1 a=2$[0];', 11, 11, '|var|_|x6c|x6e|x70|x65|x61|x77|x6f|'.split('|'), 0, {})); 56 window.v = "_fa16f708d6903a1c4b46a732b68c4c6a"; 57 $ = ~[]; 58 $ = { 59     ___: ++$, 60     $$$$: (![] + "")[$], 61     __$: ++$, 62     $_$_: (![] + "")[$], 63     _$_: ++$, 64     $_$$: ({} + "")[$], 65     $$_$: ($[$] + "")[$], 66     _$$: ++$, 67     $$$_: (!"" + "")[$], 68     $__: ++$, 69     $_$: ++$, 70     $$__: ({} + "")[$], 71     $$_: ++$, 72     $$$: ++$, 73     $___: ++$, 74     $__$: ++$ 75 }; 76 $.$_ = ($.$_ = $ + "")[$.$_$] + ($._$ = $.$_[$.__$]) + ($.$$ = ($.$ + "")[$.__$]) + ((!$) + "")[$._$$] + ($.__ = $.$_[$.$$_]) + ($.$ = (!"" + "")[$.__$]) + ($._ = (!"" + "")[$._$_]) + $.$_[$.$_$] + $.__ + $._$ + $.$; 77 $.$$ = $.$ + (!"" + "")[$._$$] + $.__ + $._ + $.$ + $.$$; 78 $.$ = ($.___)[$.$_][$.$_]; 79 $.$($.$($.$$ + "\"" + $.$$$$ + $._ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.__ + "\\" + $.__$ + $.$_$ + $.__$ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.$__ + $.___ + "\\" + $.__$ + $.$$_ + $.___ + "(\\" + $.__$ + $.$$_ + $._$$ + ")\\" + $.$__ + $.___ + "{\\" + $.__$ + $.$$_ + $._$_ + $.$$$_ + $.__ + $._ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.$__ + $.___ + "\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $._$_ + ",\\" + $.$__ + $.___ + $.$__ + ")." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "('\\" + $.__$ + $.$_$ + $.$$_ + "')." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "(\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $.___ + ",\\" + $.$__ + $.___ + $.__$ + "))." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "('\\" + $.__$ + $.$$_ + $.___ + "')." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "(\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $.$__ + ",\\" + $.$__ + $.___ + $.$___ + "))." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "('" + $.$$$_ + "')." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "(\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $.__$ + ",\\" + $.$__ + $.___ + $._$_ + "))." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "(\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $.__$ + $.$$_ + "))." + $.$$__ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.$_$_ + $.__ + "(\\" + $.__$ + $.$$_ + $._$$ + ".\\" + $.__$ + $.$$_ + $._$$ + $._ + $.$_$$ + "\\" + $.__$ + $.$$_ + $._$$ + $.__ + "\\" + $.__$ + $.$$_ + $._$_ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + "\\" + $.__$ + $.$__ + $.$$$ + "(" + $.$___ + ",\\" + $.$__ + $.___ + $.__$ + $.$$_ + "));};\\" + $.$__ + $.___ + "\\" + $.__$ + $._$_ + "+" + $.$$$$ + $._ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$__ + $.__ + "\\" + $.__$ + $.$_$ + $.__$ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + "(){" + $.$$_$ + $._$ + $.$$__ + $._ + "\\" + $.__$ + $.$_$ + $.$_$ + $.$$$_ + "\\" + $.__$ + $.$_$ + $.$$_ + $.__ + "." + $.$$__ + $._$ + $._$ + "\\" + $.__$ + $.$_$ + $._$$ + "\\" + $.__$ + $.$_$ + $.__$ + $.$$$_ + "\\" + $.$__ + $.___ + "=\\" + $.$__ + $.___ + "\\\"\\" + $.__$ + $.$_$ + $._$_ + "\\\"\\" + $.$__ + $.___ + "+\\" + $.$__ + $.___ + "\\\"_\\\"\\" + $.$__ + $.___ + "+\\" + $.$__ + $.___ + "\\\"" + $.__ + $._$ + "\\" + $.__$ + $.$_$ + $._$$ + $.$$$_ + "\\" + $.__$ + $.$_$ + $.$$_ + "=\\\"\\" + $.$__ + $.___ + "+\\" + $.$__ + $.___ + "\\" + $.__$ + $.$$_ + $.___ + "(\\" + $.__$ + $.$$_ + $.$$$ + "\\" + $.__$ + $.$_$ + $.__$ + "\\" + $.__$ + $.$_$ + $.$$_ + $.$$_$ + $._$ + "\\" + $.__$ + $.$$_ + $.$$$ + ".\\" + $.__$ + $.$$_ + $.$$_ + ");" + (![] + "")[$._$_] + $._$ + $.$$__ + $.$_$_ + $.__ + "\\" + $.__$ + $.$_$ + $.__$ + $._$ + "\\" + $.__$ + $.$_$ + $.$$_ + ".\\" + $.__$ + $.$$_ + $._$_ + $.$$$_ + (![] + "")[$._$_] + $._$ + $.$_$_ + $.$$_$ + "();}();" + "\"")())();

  能够发现这是一段通过js混淆后的代码(我到如今都不知道最后那段丧心病狂的代码是如何产生的T.T),咱们能够将此代码分红三个部分,再分别运行一下了解其功能;具体的分析过程原文里已经讲的很清楚了,你们能够去原文连接里去看。

二、破解结果

  根据原文的破解咱们能够知道,第一个页面其实就是产生一个‘j_token'并将其添加到cookies里而且重新请求一下页面,原文里的解决方法是将产生j_token的代码用python重写,当js代码很简单的时候这样固然能够,但当js代码很是复杂的时候就很难办了。因此我使用了一种在python里使用execjs模块运行js代码的方式来产生j_token,下面是个人代码;

 1 import requests  2 import re  3 import execjs  4 
 5 
 6 class OpenLawSpider():  7     def __init__(self):  8         self.url = "http://openlaw.cn/search/judgement/default?lawyerId=0904484bbc1e46f99d52744427b533d9"
 9         self.headers = { 10             'Host': 'openlaw.cn', 11             'User-Agent': 'Mozilla/5.0(Windows NT 10.0;Win64;x64;rv: 60.0) Gecko/20100101Firefox/60.0', 12             'Accept': 'text/html, application/xhtml + xml, application/xml;q = 0.9,*/*;q = 0.8', 13             'Accept-Language': 'zh-CN,zh;q = 0.8, zh-TW;q = 0.7, zh-HK;q = 0.5, en-US;q = 0.3, en;q = 0.2', 14             'Accept-Encoding': 'gzip, deflate', 15             'Connection': 'keep-alive', 16             'Cache - Control': 'max-age = 0', 17  } 18         self.jscode = '''function p(s) { 19  return s.substring(2, 4).concat('n').concat(s.substring(0, 1)).concat('p').concat(s.substring(4, 8)).concat('e').concat(s.substring(1, 2)).concat(s.substring(16)).concat(s.substring(8, 16)); 20  };'''
21         self.proxies = { 22                           "https": "http://202.38.92.100:3128", 23  } 24 
25     def get_val_v(self): 26         js_res = requests.get(self.url, headers = self.headers) 27         js_html = js_res.text 28         pat = re.compile('window.v="(.*?)";', re.S) 29         v = re.findall(pat, js_html)[0] 30         cookies = requests.utils.dict_from_cookiejar(js_res.cookies) 31         print(v) 32         return v, cookies 33 
34     def get_cookie(self): 35         v, cookies = self.get_val_v() 36         ctx = execjs.compile(self.jscode) 37         cookie = ctx.call('p', v) 38         cookies['j_token'] = cookie 39         print(cookies) 40         return cookies 41 
42     def get_page_html(self): 43         cookies = self.get_cookie() 44         page_res = requests.get(self.url, headers=self.headers, cookies=cookies, proxies=self.proxies) 45         print(page_res.text) 46 
47 
48 
49 if __name__ == "__main__": 50     spider = OpenLawSpider() 51     spider.get_page_html()

三、代码运行结果

网页截图:

 

能够发现咱们已经获得了想要获取的页面了。

可是:当我在写这篇博客的时候再次运行了一次代码,居然出现下图(宝宝内心苦,宝宝不说T.T)

  

 

我只是简单的获取了一个页面的html,并且只运行了一次,第二次就被封了,可见这个网站的反爬力度仍是很大的,我只好在网上换了个ip才再次获得告终果,看来想要爬取这个网站的人还要准备好ip代理了。。。

4、总结

  通过了此次的模仿实践,也算是了解到了js混淆反爬的大体方式,其实以前遇到js加密时我还想到了使用selenium去抓取,可是不少人说模拟浏览器是爬虫最后的一种方法,并且selenium爬取速度很慢,因此学习一下突破js混淆反爬仍是颇有必要的。最后,我还想说一下其实还有另外一种最强的爬虫方案,就是人工一页一页的去翻网页,再将想要的数据记录下来,看你怎么反爬,这就是最强的人工爬虫,又名:网络爬人。(最后开个玩笑,你们略过就好)

相关文章
相关标签/搜索