zoukankan      html  css  js  c++  java
  • 【爬虫】callback=jQuery+数字在爬虫中如何模拟

    原文链接:https://www.cnblogs.com/SnowPhoenix/p/15674155.html

    问题描述

    从浏览器查看请求信息的时候,我们会发现有些请求有这样的特征:

    1. 包含一个类似于?callback=jQuery17209708769256472376_1639142208410&jsonp=jsonp&_=1639142206313的query;
    2. 返回的JSON数据jQuery17209708769256472376_1639142208410({"code":0,"message":"","data":{"uid":123}}),返回的字符串就是请求时url的callback调用了本身应该返回的数据;
    3. 简单将这个url复制到Postman请求会失败;

    简单搜索一下,可以知道这个是jQuery在进行跨域请求的时候利用jsonp进行处理造成的现象。注意几点:

    1. 需要设置Referer头,因为这是跨域请求,这也是为什么直接复制到Postman会失效的原因,Postman中加了Referer头之后也能成功;
    2. _=1639142206313其实就是时间戳,没什么好说的;
    3. 想要获得原始的JSON数据,在获得返回数据后,直接前后的JSONP的padding删去即可;

    但是这里有个问题,我们怎么模拟callbackjQueryxxxxx的生成呢?

    参考

    替代解决方案

    既然我们知道这一套操作是跨域时的问题,那么我们的爬虫直接不进行跨域请求即可。即

    • 删去callbackjsonp_(写时间戳的那个)这三个query;
    • 删去Referer头,或者将Referer头设置为当前请求的url的域名;

    当然,这样的解决方案不是很优雅,虽然我js水平很烂,也没学过jQuery,但我还是决定看看jQuery来看看这个这个jQueryxxxxx是如何生成的。

    jQuery源码

    jsonpcallback来进行搜索,在jquery.js文件里可以看到这样的代码:

    // Default jsonp settings
    jQuery.ajaxSetup( {
    	jsonp: "callback",
    	jsonpCallback: function() {
    		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce.guid++ ) );
    		this[ callback ] = true;
    		return callback;
    	}
    } );
    

    前面oldCallbacks.pop()应该是一个callback池,如果有空余的就不用产生新的了,不过我们需要关注的是新的是如何产生的:( jQuery.expando + "_" + ( nonce.guid++ ) )

    继续找expando,在jquery.js文件里能够找到这样的代码:

    jQuery.extend( {
    
    	// Unique for each copy of jQuery on the page
    	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
    
    	// Assume jQuery is ready without the ready module
    	isReady: true,
    
    	error: function( msg ) {
    		throw new Error( msg );
    	},
    

    这就能够知道了,再看我们示例的jQuery17209708769256472376_1639142208410,前面172,就应该是版本号1.7.2将非数字删去的结果,Math.random()产生0-1间的浮点数,然后将小数点删去,得到了09708769256472376,是十分符合的。

    但是我通过多次在浏览器刷新,发现示例中的jQuery17209708769256472376_1639142208410结尾1639142208410显然是个时间戳,而不像是guid++产生的结果。我目前看的源码是3.x版本的源码,回去看看1.x的源码,在jquery1.9.1.js文件中可以看到相对应的代码:

    // Default jsonp settings
    jQuery.ajaxSetup( {
    	jsonp: "callback",
    	jsonpCallback: function() {
    		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( ajax_nonce++ ) );
    		this[ callback ] = true;
    		return callback;
    	}
    } );
    

    这里用的是ajax_nonce++,而往上找,就能找到它的定义:

    ajax_nonce = jQuery.now(),
    

    即为当前的时间戳。

    python代码

    import time
    import random
    
    class Constant:
        jQuery_Version = "1.7.2"
    
    def get_current_timestamp() -> int:
        return int(round(time.time() * 1000))
    
    def jquery_mock_callback() -> str:
        "jQuery" + (Constant.jQuery_Version + str(random.random())).replace(".", "") + "_" + str(get_current_timestamp() - 1000)
    
  • 相关阅读:
    如何编写 maptalks plugin
    maptalks 如何加载 ArcGIS 瓦片图层
    vue 地图可视化 maptalks 篇
    个人博客如何开启 https
    vue.js多页面开发环境搭建
    vue 自动化部署 jenkins 篇
    virtualbox ubuntu 安装 openssh-server
    从零开始学 Spring Boot
    数据结构
    vue 转换信息为二进制 并实现下载
  • 原文地址:https://www.cnblogs.com/SnowPhoenix/p/15674155.html
Copyright © 2011-2022 走看看