【问题标题】:Bypassing "Honeypots" when scraping抓取时绕过“蜜罐”
【发布时间】:2019-05-19 13:52:06
【问题描述】:

我一直在尝试从网页中提取一些数据,它使用一些特殊的方法来检测我需要绕过的机器人。 我首先不得不绕过烦人的CAPTCHA,但现在又出现了另一个问题。

网页使用(似乎是)随机链接生成器为我提供我想要的数据。在浏览器上,只有一个按钮可见,但通过查看源代码,我在同一区域看到多个随机生成的按钮,如下所示:

...
<div id='BA405352A9' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=A230134'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='075A1762B3' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=7294A7B'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='453A2A0469' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=9646432'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='302B375583' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=933A29B'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='08171153B4' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=3447182'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='20813B7B10' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=6B96496'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='6661917AB6' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=9AA8604'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div><div id='1646980B02' style='display:none;'><button type="button" value="Upgrade level" class="build" onclick="window.location.href = 'dorf2.php?a=20&c=5841731'; return false;">
<div class="button-container"><div class="button-position"><div class="btl"><div class="btr"><div class="btc"></div></div></div>
<div class="bml"><div class="bmr"><div class="bmc"></div></div></div><div class="bbl"><div class="bbr"><div class="bbc"></div></div></div>
</div><div class="button-contents">Enter</div></div></button></div></div><script language="javascript">
...

根据来源,最初的 HTTP GET 请求似乎只包含不可见的按钮,并且不知何故在 CSS 加载后“正确”按钮变得可见?

我对这样的设计(或一般的网站设计)没有那么丰富的经验。它们是如何工作的?我怎样才能模仿浏览器的行为来绕过它们?

【问题讨论】:

  • 也许您可以购买许可证并访问 api...?
  • @thebjorn 不幸的是,这样的 API 还不存在
  • 这似乎是一个应该通过电子邮件发送给网站所有者的问题。显然,他们不希望机器人抓取他们的网站,所以也许你可以达成某种协议。
  • 很可能 css 被键入到唯一 id。由于样式可以从其他样式继承,如果样式没有通过多层进行混淆,我会感到惊讶。
  • 该网站最后一次更新是在 2012 年!我认为在这个阶段,任何头脑正常的人都不会想要寻找 API 或联系开发人员。至于我是否“被允许”这样做,像这样的网页不会问我是否“允许”使用我的私人信息,或者是否“允许”记录我的行为并让我不知所措带广告。所以我认为我可以从这个网站上抓取任何我想要的东西。

标签: python web-scraping python-requests


【解决方案1】:

我终于可以访问数据了,原来CSS标签是在页面加载时被一些Javascript设置的。查看脚本后,我发现生成了很多数据(可能是服务器端),我需要先提取这些数据。
经过数小时的查找,我终于能够找到 Javascript 用来编辑数据的函数。有一堆,服务器随机使用它们的顺序来进一步混淆任何破解算法的尝试:

function showbt(sid) {
            return (dM(aM(bM(fM(gM(cM(sid)))))))
        }

这里的顺序是随机生成的,其中2个函数被注入到网页源码里面,每次都要替换。

我能够将 Javascript 完全翻译成 Python,并使用 rerequests 提取和更新函数及其使用顺序,然后使用生成的 Python 代码最终破解加密。 (翻译示例:)

var _0x7052 = ["", "\x6C\x65\x6E\x67\x74\x68", "\x73\x75\x62\x73\x74\x72", "\x69\x6E\x64\x65\x78\x4F\x66"];

function aarf(_0xb5a3x2) {
    var _0xb5a3x3 = 0;
    var _0xb5a3x4 = 0;
    var _0xb5a3x5 = _0x7052[0];
    for (i = 0; i < _0xb5a3x2[_0x7052[1]]; i += 1) {
        _0xb5a3x3 = stream[_0x7052[3]](_0xb5a3x2[_0x7052[2]](i, 1));
        _0xb5a3x3 = _0xb5a3x3 * _0xb5a3x3 + 6 * _0xb5a3x3 + 6246;
        _0xb5a3x3 = _0xb5a3x3 % stream[_0x7052[1]];
        _0xb5a3x5 += stream[_0x7052[2]](_0xb5a3x3, 1);
    };
    return _0xb5a3x5;
};

将 UTF-8 翻译成文本(这里是用来混淆代码的):

var _0x7052 = ["", "length", "substr", "indexOf"];

function aarf(_0xb5a3x2) {
    var _0xb5a3x3 = 0;
    var _0xb5a3x4 = 0;
    var _0xb5a3x5 = _0x7052[0];
    for (i = 0; i < _0xb5a3x2[_0x7052[1]]; i += 1) {
        _0xb5a3x3 = stream[_0x7052[3]](_0xb5a3x2[_0x7052[2]](i, 1));
        _0xb5a3x3 = _0xb5a3x3 * _0xb5a3x3 + 6 * _0xb5a3x3 + 6246;
        _0xb5a3x3 = _0xb5a3x3 % stream[_0x7052[1]];
        _0xb5a3x5 += stream[_0x7052[2]](_0xb5a3x3, 1);
    };
    return _0xb5a3x5;
};

最后将JS的数组函数代入Python重写后得到:

def aarf(_0xb5a3x2) :
    _0xb5a3x3 = 0
    _0xb5a3x4 = 0
    _0xb5a3x5 = ""
    for i in range(0, len(_0xb5a3x2), 1): 
        _0xb5a3x3 = stream.index(_0xb5a3x2[i:i+1])
        _0xb5a3x3 = _0xb5a3x3 * _0xb5a3x3 +6 * _0xb5a3x3 +6246 #REPNUM2
        _0xb5a3x3 = _0xb5a3x3 % len(stream)
        _0xb5a3x5 += stream[math.ceil(_0xb5a3x3):math.ceil(_0xb5a3x3)+1]
    return _0xb5a3x5
#note that the REPNUM comment indicates there are 2 randomly generated numbers in this line, and they'll have to be extracted from the webpage and injected into this code.

但还没有……

按钮本身是由网页生成的,其中的 ID 也已加密,因此我必须通过与上述相同的步骤来解密按钮 ID。

剩下的就是将解密后的按钮 ID 与解密后的 Javascript 代码的输出进行匹配,然后找到要使用的正确按钮!


对于任何想要做类似事情的人,请记住,用于解密右侧按钮的 Javascript 总是以某种方式包含在网页中(否则您的浏览器也找不到正确的!),所以您需要做的就是非常仔细地分析网页及其工作方式,然后尝试对其行为进行逆向工程以利用加密。

我能够在没有太多 javascript 或 HTML 经验的情况下做到这一点,所以如果我能做到,你也能做到! 另一种解决方法是使用Selenium,但这并没有使用旧的requests 的功能和速度的一小部分!

【讨论】:

  • 你肯定花了很长时间。与此相比,Selenium 的设置相当容易,并且可以为您节省大量时间。但它不会打败recaptchas。
猜你喜欢
  • 1970-01-01
  • 2013-05-27
  • 2013-10-12
  • 1970-01-01
  • 2022-06-10
  • 2020-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多