Python 中的网页抓取 - Arraybuffer 到数据可读

Orr*_*her 5 python web-scraping arraybuffer

我正在为 Hoymiles 监控系统开发一个网络爬虫。我可以获得的统计数据之一是历史数据,但我获得的数据格式很奇怪。经过大量研究和平台代码搜索后,我发现在发出的post请求中,除了标头和有效负载之外,他们还使用了一个参数,即responseType:“arraybuffer”。因此,经过更多研究,我发现 arraybuffer 是“一种用于表示通用、固定大小的二进制数据缓冲区的数据类型”。

\n

我的代码如下:

\n
def plants_data_historycal(self, authorization):\n\n    payload = \'\'\'\n        {\n            "mode":3,\n            "date":"2022-01-20"\n        }\n    \'\'\'\n\n    headers = {\n        \'Accept\': \'application/json, text/plain, */*\',\n        \'Accept-Encoding\': \'gzip, deflate, br\',\n        \'authorization\': authorization,\n        \'Content-Type\': \'application/json;charset=UTF-8\',\n        \'Origin\': \'https://global.hoymiles.com\',\n        \'Referer\': \'https://global.hoymiles.com/platform/login\',\n        \'Cookie\': cookie,\n        \'User-Agent\': \'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Mobile Safari/537.36\'\n    }\n\n    response = self.session.post(self.url+\'/pvm-data/api/0/statistics/count_station_eq\', headers=headers, data=payload)\n\n    if response.status_code != 200:\n        raise RuntimeError("A requisi\xc3\xa7\xc3\xa3o falhou: %s", response)\n\n    print(response.text)\n    data = BeautifulSoup(response.text, \'html.parser\')\n    data = json.loads(data.text)\n\n    return data\n
Run Code Online (Sandbox Code Playgroud)\n

对我的请求的响应如下所示:

\n
1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14\n15\n16\n17\n18\n19\n20Y\npv_eqP\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd@H\xef\xbf\xbd\xef\xbf\xbd[H\xef\xbf\xbdnH\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdH\xef\xbf\xbd0H\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbdQH\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd\xef\xbf\xbdH\xef\xbf\xbdJH\xef\xbf\xbd\n\xef\xbf\xbdH`\xef\xbf\xbdH\xef\xbf\xbd1\xef\xbf\xbdH\xef\xbf\xbd\xdd\x97H@]sH\xef\xbf\xbd\xef\xbf\xbd_H`j\xef\xbf\xbdH\xef\xbf\xbd!\xef\xbf\xbdH\n
Run Code Online (Sandbox Code Playgroud)\n

BeatifulSoup之前的response.text

\n
\\n\\x011\\n\\x012\\n\\x013\\n\\x014\\n\\x015\\n\\x016\\n\\x017\\n\\x018\\n\\x019\\n\\x0210\\n\\x0211\\n\\x0212\\n\\x0213\\n\\x0214\\n\\x0215\\n\\x0216\\n\\x0217\\n\\x0218\\n\\x0219\\n\\x0220\\n\\x0221\\n\\x0222\\n\\x0223\\x12e\\n\\x05pv_eq\\x12\\\\\\x00\xef\xbf\xbd\xef\xbf\xbdG\\x00\xef\xbf\xbd@H\xef\xbf\xbd\xef\xbf\xbd[H\\x00\xef\xbf\xbdnH\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdH\xef\xbf\xbd\\x080H\\x00\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbdQ\\x00H\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdG\xef\xbf\xbd\xef\xbf\xbd\\x02H\xef\xbf\xbdJ\\x03H\xef\xbf\xbd\\r\xef\xbf\xbdH`\xef\xbf\xbdH\xef\xbf\xbd1\xef\xbf\xbdH\xef\xbf\xbd\xdd\x97H@]sH\xef\xbf\xbd\xef\xbf\xbd_H`j\xef\xbf\xbdH\xef\xbf\xbd!\xef\xbf\xbdH\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbdH`z\xef\xbf\xbdH I\xef\xbf\xbdH\n
Run Code Online (Sandbox Code Playgroud)\n

为了尝试将此字符串转换为可以理解的内容,我尝试使用 Hoymiles 主页 Chrome 浏览器 ( https://global.hoymiles.com/platform/home ) 的检查选项中提供的代码。从那里我发现他们用函数转换了数组缓冲区

\n
transformResponse: [\n    function (e) {\n            if ("string" == typeof e)\n                   try {\n                        e = JSON.parse(e);\n                   } catch (e) {}\n                        return e;\n     },\n],\n
Run Code Online (Sandbox Code Playgroud)\n

但即便如此,数组缓冲区还是空的。所以我将响应作为 arraybuffer 转换为 Uint8Array,但我无法理解数据的含义。

\n
Uint8Array {\n0: 123\n1:34\n10:34\n11:49\n12:48\n13:48\n14:34\n15:44\n16:34\n17: 100\n18:97\n19: 116\n2: 115\n20: 97\n21:34\n22:58\n23:34\n24: 34\n25:44\n26: 34\n27: 109\n28: 101\n29: 115\n3: 116\n30: 115\n31: 97\n32: 103\n33: 101\n34: 34\n35: 58\n36: 34\n37: 116\n38: 111\n39: 107\n4: 97\n40: 101\n41: 110\n42: 32\n43: 118\n44: 101\n45: 114\n46: 105\n47: 102\n48: 121\n49: 32\n5: 116\n50: 101\n51: 114\n52: 114\n53: 111\n54: 114\n55: 46\n56: 34\n57: 125\n6: 117\n7: 115\n8:34\n9:58\n}\n
Run Code Online (Sandbox Code Playgroud)\n

有谁知道如何将其转化为可读或可理解的数据?

\n

car*_*eld 2

所以我不知道您期望从中得到什么数据类型Uint8Array。但以下一些见解可能会帮助您回答您的问题。Uint8Array 类型数组表示 8 位无符号整数的数组。因此,这应该代表什么是含糊不清的。它可以是 String、float、json、int。

因此,我假设您打印的 Uint8Array 输出将键视为数组中的索引位置,而值是数组中该索引处的值。然而索引 50 不是输出中的关键,所以这很令人困惑

无论如何,我制作了一个 Uint8Array,其值的顺序与下面的输出相同。


// Same array you printed out
const lst = [ 123, 34, 115, 116, 97, 116, 117, 115,  34,  58,  34,  49,  48, 
 48, 34,  44,  34,  100,  97,  116,  97,  34,  58,34,  34,  44,  34,  109,  
 101,  115,  115,  97,  103,  101,  34,  58,  34,  116,  111,  107,  101, 
 110,  32,  118,  101,  114,  105,  102,  121,  32,  undefined,  114,  114,  
  111,  114,  46,  34 ]

// Make the Uint8Array
var data = new Uint8Array(lst);

// Print as String
let str = Buffer.from(data).toString('base64');
console.log(str); // output: eyJzdGF0dXMiOiIxMDAiLCJkYXRhIjoiIiwibWVzc2FnZSI6InRva2VuIHZlcmlmeSAAcnJvci4i


// Print as float 
const floatValue =new DataView(data.buffer).getFloat64(0);
console.log(floatValue) // output: 1.3718470458079746e+285

// Print as json
function printAsJson(arr) {
  let str = "";
  for (var i=0; i<arr.byteLength; i++) {
    str += String.fromCharCode(arr[i]);
  }

  var serializedData = JSON.stringify(str);
  let message = JSON.parse(serializedData);

  console.log(message)
}
printAsJson(data); // output: {"status":"100","data":"","message":"token verify rror."

Run Code Online (Sandbox Code Playgroud)

综上所述,json 是最有意义的,看起来你有一个令牌验证错误。