Python爬虫实战H06初识浏览器指纹:Selenium是如何被反爬的图文教程

2024-12-27阅读数:29
上一篇:Python爬虫实战N04CSS伪元素反爬图文教程
下一篇:Python爬虫实战H05js逆向破解时间戳反爬图文教程

打开Python爬虫实战练习页面初识浏览器指纹:Selenium是如何被反爬的_H06_Spiderbuf,可以看到页面内容是由NordPass发布的2022年全球最常用密码列表,只是一个简单的表格,数据也只有10条。

在网页上点击右键 > 显示网页源代码,可以看到网页结构也并不复杂。HTML代码并不多,总共就88行,但在源码当中没有看到页面上显示的内容,这种情况一般是由JavaScript动态加载并渲染内容的。

F12打开谷歌浏览器开发者工具,刷新一下页面,看到network(网络)这里加载了几个文件,其中有一个JavaScript文件是值得注意的,因为其它几个文件名就能猜到它的作用,唯独有一个是看似无意义的。

HfPro9C.js

还有一个很长的字符串,我们点击它,右边就会展开详情,Headers里有api这样的关键字,api通常是后台返回数据的。我们切换到Response(响应)标签,能够看到后台返回了一个json。

[
    {
            "ranking": 1,
            "passwd": "password",
            "time_to_crack_it": "\u003c 1 Second",
            "used_count": 4929113,
            "year": 2022
        },
        {
            "ranking": 2,
            "passwd": "123456",
            "time_to_crack_it": "\u003c 1 Second",
            "used_count": 1523537,
            "year": 2022
        },
    ...

找到了数据返回的接口,而且拿到了明文json,那按理说我们这次的爬虫分析工作就差不多了,但当我们把刚才分析的api请求链接放到浏览器地址栏打开时,发现获取不到数据(中间出了Bug,导致有些人可以继续用这个链接,这里就当用不了吧^_^),也就说,我们要么继续分析这个请求链接是怎么构造的,要么就使用selenium这样的模拟浏览器。

先不管三七二十一,丢到selenium里运行一下再说。

client = webdriver.Chrome()
client.get('https://spiderbuf.cn/playground/h06')
print(client.page_source)
client.quit()

结果发现打印出来的HTML源码里也没有我们想要的数据,很多人这时候就不知道怎么办了,明明selenium就是一个浏览器,结果连selenium都获取不到,不知道该如何处理了。

此路不通,那我们就退回来,分析请求参数的构造,这时候就要想起我们刚才提到的HfPro9C.js文件的。

点击打开这个文件,发现居然是明文(实际爬虫过程中几乎没有明文js这样的好事,这里为了说明问题及思路,先不搞这么复杂)。

var user_agent = navigator.userAgent;
if ((!navigator.webdriver) & (navigator.plugins.length > 0) & (user_agent.indexOf('headless') < 0)) {
    console.log(navigator.webdriver);
    console.log(navigator.plugins.length);
    console.log(user_agent.indexOf('headless'));
    var timeStamp = Math.trunc(new Date().getTime() / 1000);
    var _md5 = md5(timeStamp);
    var s = btoa(`${timeStamp},${_md5}`);

    fetch("./h06/api/" + s).then(function (response) {
        return response.json();
    }).then(function (data) {
        var dataContent = document.getElementById('dataContent');
        data.forEach((value, index) => {
            var row = dataContent.insertRow();
            var rankingCell = row.insertCell();
            rankingCell.innerText = value.ranking;

            var passwdCell = row.insertCell();
            passwdCell.innerText = value.passwd;

            var time_to_crackItCell = row.insertCell();
            time_to_crackItCell.innerText = value.time_to_crack_it;

            var used_countCell = row.insertCell();
            used_countCell.innerText = value.used_count;
        })
    });
}

我们来逐行分析一下这个js文件代码,建议大家要往爬虫方面研究的话就要多熟悉javascript,要不然碰上混淆后的代码就无从下手了。

  • 第1行只是把浏览器的user agent 放在了一个变量里面;
  • 第2行开始做了判断,判断了webdriver、浏览器插件数量、headless关键字;
  • 第3行到第5行就是在浏览器控制台输出日志,这个可以利用起来,在普通浏览器里面刷新网页看看输出了什么,再到selenium里面刷新日志,对比一下两者输出有什么区别;
  • 第6行把时间戳放到了变量timeStamp里面;
  • 第7行把刚才的时间戳生成了一个MD5哈希值;
  • 第8行把时间戳跟md5值组装成了一个字符串,并使用了Base64编码,btoa就是对字符串进行Base64编码;
  • 再往下fetch这里,就是把刚才生成的Base64字符串组装成一个请求链接了;

到了这里,我们就可以用Python按照上面这个思路构造出合法的请求了。

url = 'http://spiderbuf.cn/h06/api/'
timestamp = str(int(time.time()))
md5_hash = hashlib.md5()
md5_hash.update(timestamp.encode('utf-8'))
md5 = md5_hash.hexdigest()
s = ('%s,%s' % (timestamp, md5))
print(s)
payload = str(base64.b64encode(s.encode('utf-8')), 'utf-8')
print(payload)
html = requests.get(url + payload, headers=myheaders).text
print(html)

我们已经通过分析JavaScript代码逻辑来编写Python代码写出我们的爬虫了,但为了弄清楚为什么selenium没有数据,我们再继续分析。

在上面分析JavaScript代码的时候,我们已经在第2行看到了判断,整个JavaScript文件里面也就这一个if语句,那selenium没有数据也肯定跟它有关。

真想就是selenium是浏览器,但有些默认的标识是与普通浏览器不一样的,而这些标识是可以通过JavaScript代码获取出来的,有些是会发送到后台的。

上面的JavaScript代码是最常见的检测模拟浏览器(也就是判断是否为爬虫)的代码,针对上面的检测,我们只需要在写爬虫代码的时候改几个选项即可。

# 创建一个webdriver选项变量
options = webdriver.ChromeOptions()
options.set_capability('goog:loggingPrefs', {'browser': 'ALL'})
# 改变navigator.webdriver 属性值
options.add_argument('--disable-blink-features=AutomationControlled')  
# 把自定义的选项传递给webdriver
client = webdriver.Chrome(options=options)

这样处理之后,我们就绕过了selenium被检测到的机制,从而通过selenium正常获取网页内容。

selenium之类的模拟浏览器,被检测到的选项远远不止以上几个值,实际上浏览器有很多特征是可以用JavaScript获取到的,这些特征一般被称为浏览器指纹。

这里有可以检测浏览器大部分特征的网页链接,大家可以去看看浏览器都有哪些指纹特征 浏览器指纹检测

这里附上有最新版本的 Chrome WebDriver 的下载链接 WebDriver下载链接

完整示例代码:示例代码