学习 JS 反爬
地址: http://openlaw.cn/login.jsp
想在指导案例中抓些内容, 需要登陆
账号密码发送会以下面方式发送
所以需要找到_csrf 和加密后的 password,_csrf 服务器生成的显示在登陆页面上, ctrl+F 搜索
ctrl+F 搜索 password, 找到一段 JS 代码, 可以看出 password 在加密后重新填入 input 再提交
需要找到加密函数 KeyEncrypt,ctrl+F 搜索
这段复制到新的 snippets, 看代码调用了 JSEncrypt,CryptoJs 继续 ctrl+F 搜索,
CRYptoJS 找到两个文件, 全都复制加到 snippets 里执行一下
获得了加密的密码部分, 下面需要让这段代码再 python 里执行, 可以用 ExecJS 和 js2py, 这里推荐用 ExecJS
把 snippets 的代码复制出来另存为 JS, 用 ExecJS 执行
这里要注意运行时环境, 如果是 node.JS 或 Jscript 都会报错不能运行, navigator is not define, 可能因为 Node.JS 和 Jscript 都不是浏览器, 试过复制个 navagator 或改写代码里 navagator 部分都有别的报错,
所以还是用 PhantomJS 比较好.
- import ExecJS
- import ExecJS.runtime_names
- os.environ["EXECJS_RUNTIME"] = "PhantomJS"
- PhantomJS = ExecJS.get(ExecJS.runtime_names.PhantomJS)
- print(ExecJS.get().name)
上面代码是运行时环境设置
运行结果, 记得 JS 路径前要加 r, 不然会报错
因为 csfr 在登陆页, post 在另一页, 所以需要写两个请求
- headers={
- "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Accept-Encoding":"gzip,deflate",
- "Accept-Language":"zh-CN,zh;q=0.9",
- "Cache-Control":"max-age=0",
- "Connection":"keep-alive",
- "Content-Type":"application/x-www-form-urlencoded",
- "Host":"openlaw.cn",
- "Upgrade-Insecure-Requests":"1",
- "User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36",
- }
- r=session.get("http://openlaw.cn/login.jsp?",headers=headers1)
- tree=etree.HTML(r.text)
- csrf=tree.xpath('//input[@name="_csrf"]/@value')[0]
- post_url="http://openlaw.cn/login"
- with open(r"C:\Users\37576\Desktop\123.js",encoding="utf-8")as f:
- JS=f.read()
- ctx = ExecJS.compile(JS)
- pwd=ctx.call("keyEncrypt","XXXXXXXX")# 密码
- data={
- "_csrf":csrf,
- "username":"#########",# 账户
- "password":pwd,
- "_spring_security_remember_me":"true",
- }
- res=session.post(post_url,data=data,headers=headers)
- tree=etree.HTML(res.text)
- lala=tree.xpath('//div[@class="bbp-user-section"]//text()')
账户密码已擦掉, 运行结果
已经登陆成功了
下面开始抓取页面
- url="http://openlaw.cn/guidance/16444eba67afe97881fa6521d333ef10"
- headers1={
- "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3",
- "Accept-Encoding":"gzip,deflate",
- "Accept-Language":"zh-CN,zh;q=0.9",
- "Connection":"keep-alive",
- "Host":"openlaw.cn",
- "Upgrade-Insecure-Requests":"1",
- "User-Agent":"Mozilla/5.0(WindowsNT10.0;Win64;x64)AppleWebKit/537.36(KHTML,likeGecko)Chrome/73.0.3683.86Safari/537.36",
- }
- a=session.get(url,headers=headers1)
抓取结果全是乱码
到浏览器抓包分析一下, 这里 Chrome 和 fiddler 好像都不好用, 显示不全或者抓不到, 用火狐浏览器来抓
可以看到与刚才抓到的页面一样, 而有数据的页面在该页面下面
看请求发现地址一样, 但是有数据页面的 cookie 多了几项, 百度一下发现这是用 JS 加密 cookie, 带有新 cookie 的请求才能显示正确页面, 加密的 JS 就在上面的乱码里
百度查资料得知下面这种格式加密叫 jjencode,jjencodeDemo 地址: http://utf-8.jp/public/jjencode.html
- ],_$_:++$,$_$$:({
- }+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[
- +[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]
这种加密叫 jsfunk, 地址是: http://www.jsfuck.com/
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((゚ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];
还有一种是 aaencode, 地址是 http://utf-8.jp/public/aaencode.html
原理就不写了, 可以自己百度, 就算知道了也解不开
这些代码在 JS 里都是能执行的, 把第一行乱码复制到 snippets 里执行, 直接执行没有结果, 删掉结尾自执行函数括号执行显示出函数内容
- (function anonymous() {
- if (Windows.wp1) {
- document.cookie = 'OPEN_E4C0C08491=' + wp3;
- document.cookie = 'OPEN_ID=B32pJOwfO/AJZJ3ZGmnunQNTaUie84jnyHoNCq/onZQ='
- }
- }
- )
看到这个果然是添加 cookie, 下面一行复制, 全部执行
执行失败, wp3 是给出的变量没复制, 但是点击报错得到了解析后的代码
把前面的代码拼起来
- var wp1 = 'xKIOt5jUZQcS8wurcX4lghwlET9K0IWBUsS3ZqmSamCBTAPg7Fl5sVr443dyK42p';
- var wp2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
- var wp3 = "548545fe3ced4f3494934e537e304705";
- var wp4 = "464acf618bf62df3e7e37e80c2c1a04d";
- var wp5 = "0aa9566c4aa30883e34d0e1a530bf508";
- var wp6 = "a8f49232d343e4b94ff7958088fa6734";
- var wp7 = "82f778b45a9fce8589105c852174947b";
- var wp8 = "3221d819c9b96d2631d0b5084c736f69";
- (function anonymous() {
- if (Windows.wp1) {
- document.cookie = 'OPEN_E4C0C08491=' + wp3;
- document.cookie = 'OPEN_ID=B32pJOwfO/AJZJ3ZGmnunQNTaUie84jnyHoNCq/onZQ='
- }
- }
- )
- (function anonymous() {
- var getGlobal = function() {
- if (typeof self !== '') {
- return self
- }
- ;if (typeof Windows !== '') {
- return Windows
- }
- ;if (typeof global !== '') {
- return global
- }
- ;throw new Error('unable to locate global object')
- };
- function _process(s) {
- var result = s.substring(5, 7).concat('s').concat(s.substring(14, 15)).concat('v').concat(s.substring(9, 13)).concat('g').concat(s.substring(5)).concat('l').concat(s.substring(11, 19));
- return result.substr(0, 32);
- }
- ;var _switch = false;
- if ((getGlobal() === Windows)) {
- _switch = true
- } else {
- _switch = false
- }
- ;document.cookie = 'SIGNIN_ID=3e2291010f36c9244c633aba4cdcdd42';
- document.cookie = 'SIGNIN_UC=9e65d8fc646e49fb7a0f9f8237915bfb';
- document.cookie = 'UNDEFINED=432e9111ecf89746f3046ca970814f41';
- if (_switch) {
- document.cookie = 'OPEN_589D5869B5=' + _process(wp3);
- setTimeout("location.reload();", 100);
- }
- }
- )
找到了修改 cookie 的代码, 可以看出有六条 cookie 修改, 修改完后通过 location.reload(); 刷新页面, 因为有新 cookie 所以刷新后的页面是有数据的页面
至此卡住
想抓到这一页拿到 script 里的内容, 后面添加一个函数输出 cookie, 用 ExecJS 执行这段代码拿到新 cookie 重新请求页面, 但实际操作中各种报错, 只能暂时放下, 等日后水平提高再来.
下面用 webdriver 大法
- from selenium import webdriver
- from selenium.webdriver.Chrome.options import Options
- chrome_options = Options()
- chrome_options.add_argument('--headless')
- driver = webdriver.Chrome(chrome_options=chrome_options,executable_path = 'D:\python\chromedriver.exe')
- from time import sleep
配置谷歌无头浏览器
- driver.get("http://openlaw.cn/login.jsp?logout")
- driver.find_element_by_id("username").send_keys("XXXXXXXXX")
- driver.find_element_by_id("password").send_keys("XXXXXXXXX")
- sleep(2)
- driver.find_element_by_id("submit").click()
登陆账号
- driver.get("http://openlaw.cn/guidance/167ce490ba94c3ed26baab5689fdd620")
- sleep(2)
- title=driver.find_element_by_xpath('//h1[@class="entry-title"]').text
- guid=driver.find_element_by_xpath('//div[@class="annotator-wrapper"]/p').text
- content=driver.find_element_by_xpath('//div[@class="annotator-wrapper"]/p[2]').text
- page_detail={
- "title":title,"content":guid+"\n"+content.replace("\u3000"," ")
- }
跳转页面抓取数据
结果
总结
1. 网站登陆用到了 RSA 算法加密密码, RSA 这三篇文章讲的很好, 可以学习一下 地址: https://blog.csdn.net/u014044812/article/details/80782448,
2. 在用浏览器访问的时候基本打开一页就要输一遍验证码, 感觉大量抓取用打码平台的话应该会多花不少钱
3. 访问页面用了 cookie 加密, 加密的 JS 用到了两种混淆方法和 eval 函数, 在线解密网站不太好用, 谷歌浏览器自带的 snippets 很好用, 断点调试不是很会用
4. 作为新手这种网站难度有些大, 最后只能用 webdriver
来源: https://www.cnblogs.com/shenyiyangle/p/10743133.html