zoukankan      html  css  js  c++  java
  • 【Python3爬虫】常见反爬虫措施及解决办法(三)

     上一篇博客的末尾说到全网代理IP的端口号是经过加密混淆的,而这一篇博客就将告诉你如何破解!如果觉得有用的话,不妨点个推荐哦~

    一、全网代理IP的JS混淆

    首先进入全网代理IP,打开开发者工具,点击查看端口号,看起来貌似没有什么问题:

    如果你已经爬取过这个网站的代理,你就会知道事情并非这么简单。如果没爬过呢?也很简单,点击鼠标右键然后查看网页源代码,搜索”port“,可以找到如下内容:

    很明显这不是网页上显示的端口号了,那我们要怎么才能得到真正的端口号呢?

    解决办法:

     首先需要找到一个JS文件:http://www.goubanjia.com/theme/goubanjia/javascript/pde.js?v=1.0,点开后可以看到如下内容:

    这么复杂的JS代码看得人头都大了,不过我们发现这个JS代码是一个eval函数,那我们能不能把它解码一下呢?这时候你需要一个工具--脚本之家在线工具,把这些JS代码复制进去:

     然后点击解码:

     

    还是一个eval函数,所以再次解码:

    到这一步,已经比最开始的代码简洁多了,但是还易读性还是很差,所以我们需要先格式化一下:

    var _$ = [
    "x2ex70x6fx72x74",
    "x65x61x63x68",
    "x68x74x6dx6c",
    "x69x6ex64x65x78x4fx66",
    "x2a",
    "x61x74x74x72",
    "x63x6cx61x73x73",
    "x73x70x6cx69x74",
    "x20",
    "",
    "x6cx65x6ex67x74x68",
    "x70x75x73x68",
    "x41x42x43x44x45x46x47x48x49x5a",
    "x70x61x72x73x65x49x6ex74",
    "x6ax6fx69x6e",
    ""
    ];
    $(function() {
    $(_$[0])[_$[1]](function() {
    var a = $(this)[_$[2]]();
    if (a[_$[3]](_$[4]) != -0x1) {
    return;
    }
    var b = $(this)[_$[5]](_$[6]);
    try {
    b = b[_$[7]](_$[8])[0x1];
    var c = b[_$[7]](_$[9]);
    var d = c[_$[10]];
    var f = [];
    for (var g = 0x0; g < d; g++) {
    f[_$[11]](_$[12][_$[3]](c[g]));
    }
    $(this)[_$[2]](window[_$[13]](f[_$[14]](_$[15])) >> 0x3);
    } catch (e) {}
    });
    });

    可以看到有一个列表和一个函数,而这个函数应该就是混淆的函数了,但是这列表里的数据都是十六进制的,还需要解码一下(这一步可以用Python来做):

    _ = ["x2ex70x6fx72x74", "x65x61x63x68", "x68x74x6dx6c", "x69x6ex64x65x78x4fx66", "x2a",
    "x61x74x74x72", "x63x6cx61x73x73", "x73x70x6cx69x74", "x20", "", "x6cx65x6ex67x74x68",
    "x70x75x73x68", "x41x42x43x44x45x46x47x48x49x5a", "x70x61x72x73x65x49x6ex74",
    "x6ax6fx69x6e", ""
    ]
    _ = [i.encode('utf-8').decode('utf-8') for i in _]
    print(_)
    # ['.port', 'each', 'html', 'indexOf', '*', 'attr', 'class', 'split', ' ', '', 'length', 'push', 'ABCDEFGHIZ', 'parseInt', 'join', '']

    然后把这个列表里的元素添加到上面的JS函数中,可以得到如下结果:

     1 $(function() {
     2   $(".port")["each"](function() {
     3     var a = $(this)["html"]();
     4     if (a["indexOf"]("*") != -0x1) {
     5       return;
     6     }
     7     var b = $(this)["attr"]("class");
     8     try {
     9       b = b["split"](" ")[0x1];
    10       var c = b["split"]("");
    11       var d = c["length"];
    12       var f = [];
    13       for (var g = 0x0; g < d; g++) {
    14         f["push"]("ABCDEFGHIZ"["indexOf"](c[g]));
    15       }
    16       $(this)["html"](window["parseInt"](f["join"]("")) >> 0x3);
    17     } catch (e) {}
    18   });
    19 });

    可以看到这段JS代码就是先找到每个端口节点,然后把端口的class值提取出来,再进行拆分字符串,然后获取每个字母在”ABCDEFGHIZ“中的下标值,并把这些值拼接成字符串,再转为整型数据,最后把这个整型数据向右移3位。比如”GEA“对应的下标组成的字符串是”640“,转为整型数据后向右移3位的结果就是80,也就是真实的端口值了。最后附上用Python解密端口号的代码:

    1 et = etree.HTML(html)
    2 port_list = et.xpath('//*[contains(@class,"port")]/@class')
    3 for port in port_list:
    4     port = port.split(' ')[1]
    5     num = ""
    6     for i in port:
    7         num += str("ABCDEFGHIZ".index(i))
    8     print(int(num) >> 3)

    二、用图片代替文字

    之前就有人评论说有的网站使用图片代替文字以实现反爬虫,然后我这次就找到了一个网站--新蛋网,随意点击一个商品查看一下:

    打开开发者工具,然后点击查看价格,想不到价格居然是通过图片来显示的:

    解决办法:

     我找到两个可以得到价格的办法,一个简单的,一个难一点的。简单的方法是用正则表达式,因为在源码中的其他地方是包含商品的基本信息的,比如名称和价格,所以我们可以使用正则表达式进行匹配,代码如下:

    1 import re
    2 import requests
    3 
    4 
    5 url = "https://www.newegg.cn/Product/A36-125-E5L.htm?neg_sp=Home-_-A36-125-E5L-_-CountdownV1"
    6 res = requests.get(url)
    7 result = re.findall("name:'(.+?)', price:'(.+?)'", res.text)
    8 print(result)

    难一点的方法是把图片下载到本地之后进行识别,由于这个图片的清晰度很高,也没有扭曲或者加入干扰线什么的,所以可以直接使用OCR进行识别。但是用这种方法的话需要安装好Tesseract-OCR,这个工具的安装过程还是比较麻烦的。用这种方法破解的代码如下:

     1 import requests
     2 import pytesseract
     3 from PIL import Image
     4 from lxml import etree
     5 
     6 
     7 url = "https://www.newegg.cn/Product/A36-125-E5L.htm?neg_sp=Home-_-A36-125-E5L-_-CountdownV1"
     8 res = requests.get(url)
     9 et = etree.HTML(res.text)
    10 img_url = et.xpath('//*[@id="priceValue"]/span/strong/img/@src')[0]
    11 with open('price.png','wb') as f:
    12      f.write(requests.get(img_url).content)
    13 pytesseract.pytesseract.tesseract_cmd = 'E:/Python/Tesseract-OCR/tesseract.exe'
    14 text = pytesseract.image_to_string(Image.open('price.png'))
    15 print(text)
    16 # 6999.00
  • 相关阅读:
    [LeetCode] 314. Binary Tree Vertical Order Traversal
    [LeetCode] 139. Word Break
    [LeetCode] 540. Single Element in a Sorted Array
    [LeetCode] 1443. Minimum Time to Collect All Apples in a Tree
    [LeetCode] 1442. Count Triplets That Can Form Two Arrays of Equal XOR
    [LeetCode] 1441. Build an Array With Stack Operations
    [LeetCode] 277. Find the Celebrity
    [LeetCode] 1232. Check If It Is a Straight Line
    [LeetCode] 10. Regular Expression Matching
    [LeetCode] 1192. Critical Connections in a Network
  • 原文地址:https://www.cnblogs.com/TM0831/p/10454884.html
Copyright © 2011-2022 走看看