curl如何抓取使用加速乐服务的站点?

圈UU
  • 40

很多网站使用了CDN服务,例如:seebug.(org)

其中使用加速乐的站点浏览器可以正常访问,但如果使用curl返回的是一段加密过的JS,分析后是因为Cookie的原因,如果浏览器访问会有两个cookie,并且是动态的cookie。用curl访问只有一个cookie,返回的JS里有相关的加密代码,如:

var x = "toString@_phantom@Sat@17@Expires@YCTTvH@1@2@i@function@1500@href@div@innerHTML@window@Ge3@3@f@__phantomas@challenge@replace@dc@createElement@r@location@GK@jziJ@cd@for@a@setTimeout@257@G2@3D@join@charAt@length@04@firstChild@GMT@36@while@document@match@var@__jsl_clearance@aF@toLowerCase@46@54@30@x@substr@l@return@parseInt@https@cookie@Sep@h@1506743214@Path@captcha@0@if@try@addEventListener@catch@e@false@DOMContentLoaded@else@attachEvent@onreadystatechange".replace(/@*$/, "").split("@"),
    y = "1k 24=a(){1h(f.2||f.j){};1k 13,m='1l=2b.17|2e|';1k i=[a(22){25 22},a(22){25 22;},(a(){1k 2a=1i.n('d');2a.e='<15 c=\\'/\\'>22</15>';2a=2a.1e.c;1k o=2a.1j(/27?:\\/\\//)[2e];2a=2a.23(o.1c).1n();25 a(22){14(1k 9=2e;9<22.1c;9++){22[9]=2a.1b(22[9])};25 22.1a('')}})(),a(22){14(1k 9=2e;9<22.1c;9++){22[9]=26(22[9]).1(1g)};25 22.1a('')}];13=[[-~(-~[8])],'12',(((+!+{})+[-~(+!+{})])/[-~(+!+{})]+[]+[[]][~~{}]),'g',[(-~(+!+{})+[])+[([-~(+!+{})]+~~{}>>-~(+!+{}))]],[[((-~[]<<-~[]))*[((+!+{})+(+!+{}))*[(+!+{})+(+!+{})]]]],'11',[-~(-~[8])],'1m',((((+!+{})+(+!+{})^-~~~!{}))/~~[]+[[[]][~~[]], []][-~[]]).1b(~~{}),'18',((((+!+{})+(+!+{})^-~~~!{}))/~~[]+[[[]][~~[]], []][-~[]]).1b(~~{}),'6',[(-~(+!+{})+[])+[(+[])]],'%19'];14(1k 9=2e;9<13.1c;9++){13[9]=i[[2e,7,2e,7,h,8,7,2e,7,2e,7,2e,7,h,7][9]](13[9])};13=13.1a('');m+=13;16('10.c=10.c.l(/[\\?|&]2d-k/,\\'\\')',b);1i.28=(m+';5=3, 21-29-4 1d:1o:20 1f;2c=/;');};2f((a(){2g{25 !!f.2h;}2i(2j){25 2k;}})()){1i.2h('2l',24,2k);}2m{1i.2n('2o',24);}",
    z = 0,
    f = function(x, y) {
        var a = 0,
            b = 0,
            c = 0;
        x = x.split("");
        y = y || 99;
        while ((a = x.shift()) && (b = a.charCodeAt(0) - 77.5)) c = (Math.abs(b) < 13 ? (b + 48.5) : parseInt(a, 36)) + y * c;
        return c
    },
    g = y.match(/\b\w+\b/g).sort(function(x, y) {
        return f(x) - f(y)
    }).pop();
while (f(g, ++z) - x.length) {};
eval(y.replace(/\b\w+\b/g, function(y) {
    return x[f(y, z) - 1]
}));

上边提取eval后的内容为:

var l = function() {
        while (window._phantom || window.__phantomas) {};
        var cd, dc = '__jsl_clearance=1506744182.019|0|';
        var f = [function(x) {
            return x
        }, function(x) {
            return x;
        }, (function() {
            var h = document.createElement('div');
            h.innerHTML = '<a href=\'/\'>x</a>';
            h = h.firstChild.href;
            var r = h.match(/https?:\/\//)[0];
            h = h.substr(r.length).toLowerCase();
            return function(x) {
                for (var i = 0; i < x.length; i++) {
                    x[i] = h.charAt(x[i])
                };
                return x.join('')
            }
        })(), function(x) {
            for (var i = 0; i < x.length; i++) {
                x[i] = parseInt(x[i]).toString(36)
            };
            return x.join('')
        }];
        cd = ['M', [
            [~~ {}]
        ], '5XX', [((+!~~ []) + [![],
            []
        ][-~ {}]) + ((-~ {} << -~ {}) + [
            []
        ][~~ []])], '%', ((-~ {} << -~ {}) + [
            []
        ][~~ []]), 'BJU', [((+!~~ []) + [![],
            []
        ][-~ {}]) + [-~ [(-~ {} << -~ {})]]], 'E', [((-~ {} << -~ {}) + [
            []
        ][~~ []]) + ((-~ {} << -~ {}) + [
            []
        ][~~ []])], 'A', [((+!~~ []) + [![],
            []
        ][-~ {}]) + [5]], 'A7', [((-~ {} << -~ {}) + [
            []
        ][~~ []]) + [-~ (((+!~~ []) | -~ {} - ~ {}) + (-~ {} << -~ {}) + (-~ {} - ~ {} ^ -~!{}))]], 'h', [((-~ {} << -~ {}) + [
            []
        ][~~ []]) + (-~~~ [] + (-~ {} << -~ {}) - ~~~ [] + (-~ {} << -~ {}) + [
            [],
            {}][~~!{}])], 'hg', ({} + [] + []).charAt(-~ {} - ~ {} + 6), 'U', [((-~ {} << -~ {}) + [
            []
        ][~~ []]) + [5]], 'FyQ%', [-~ [(-~ {} << -~ {})]], 'D'];
        for (var i = 0; i < cd.length; i++) {
            cd[i] = f[[1, 2, 1, 3, 1, 0, 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, 1, 0, 1, 3, 1, 0, 1][i]](cd[i])
        };
        cd = cd.join('');
        dc += cd;
        setTimeout('location.href=location.href.replace(/[\?|&]captcha-challenge/,\'\')', 1500);
        document.cookie = (dc + ';Expires=Sat, 30-Sep-17 05:03:02 GMT;Path=/;');
    };
if ((function() {
    try {
        return !!window.addEventListener;
    } catch (e) {
        return false;
    }
})()) {
    document.addEventListener('DOMContentLoaded', l, false);
} else {
    document.attachEvent('onreadystatechange', l);
}

可看到DC即是我们要的第二个cookie,

下面是重点:我使用的是PHP curl,我要如何在PHP里执行JS? 并提取上面解密后的JS结果?

我的思路是:解密JS并执行JS然后进行Cookie组合发送请求,应该就能过。但不知道PHP如何执行上面的的JS并得到结果。求解,感谢!!!

回复
阅读 1.4k
2 个回答
✓ 已被采纳

php不好办,建议使用node获取cookie后,再用php CURL 获取。

node代码如下

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch();
  const page = await browser.newPage();
  await page.goto('http://seebug.org');

  const cookie = await page.evaluate(() => {
    return document.cookie;
  });

  console.log(cookie);

  await browser.close();
})();

运行结果:

clipboard.png

类似问题可以查看我的另一个答案,也是php和node结合获取网站内容的。
https://segmentfault.com/q/10...


更新php版

<?php
// 省略引入类库的代码...

use JonnyW\PhantomJs\Client;

$client = Client::getInstance();

$binPath = '/path/to/phantomjs';// phantomjs二进制文件位置

$client->getEngine()->setPath($binPath);

$client->isLazy();

list($request, $response) = array(
    $client->getMessageFactory()->createRequest(),
    $client->getMessageFactory()->createResponse(),
);

$context = stream_context_create(array(
    'http' => array('ignore_errors' => true),
));

$html = file_get_contents('http://seebug.org', false, $context);
// 这里先把js保存到本地

$html = '<script>
delete window._phantom;
delete window.__phantomas;
window.mySetTimeout = window.setTimeout;
window.setTimeout = function () {};// 删除setTimeout方法防止网页跳转
</script>' . $html .
    '<script>mySetTimeout(function() {
      document.write(document.cookie);
    }, 200)</script>';

file_put_contents(__DIR__ . '/test.html', $html);

$request->setMethod('GET');
$request->setUrl('http://localhost/seebug/test.html');
// 这个url路径就是刚在保存的test.html路径
$request->setTimeout(1000);

$client->send($request, $response);

var_dump($response->getContent());

结果:

clipboard.png

前端时间想模拟爱奇艺的登录,也遇到和你一样的问题,系统会动态返回一段js,执行生成想要的签名参数。
不过我后端用的Python(有执行js的模块)。
我对PHP不了解,查了一下,PHP也是可以调用js函数的:
<?php echo "<script type='text/javascript'>test();</script>"; ?>
最后,我有没有了解过selenium,看看是否满足你的业务需求。这个非常方便。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
你知道吗?

宣传栏