某个 api 浏览器请求可以正常返回,但是复制请求内容到 Python 代码里就返回错误

2023-01-19 11:06:06 +08:00
 samohyes

lz 这里需要请求一个网站的 api 。

我的操作是,在同一个页面下,我打开 dev tool, 右键复制了那个请求,先 copy as fetch 在 console 中试了下,api 返回的是正确的值。然后我 copy as cmd ,将请求头等信息复制了下来,转化成 python 代码,使用 requests 库去请求。返回的就是如下。

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>TypeError: query.hash.replace is not a function<br> &nbsp; &nbsp;at ***
</html>

请求头里面也没啥东西啊,也没 cookie 。

:authority: scanapi.test.org
:method: GET
:path: /v2/***
:scheme: https
accept: */*
accept-encoding: gzip, deflate, br
accept-language: en,zh;q=0.9,zh-CN;q=0.8,en-US;q=0.7,en-GB;q=0.6
origin: https://
referer: https://
sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-dest: empty
sec-fetch-mode: cors
sec-fetch-site: same-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36

有大佬指导下这是为啥么?要如何才能成功从代码中去请求?

1388 次点击
所在节点    程序员
11 条回复
FaiChou
2023-01-19 11:14:40 +08:00
返回的头信息是什么? 感觉这是正常返回了 html, 但你的 python 环境没有 js 引擎, 所以会报一个 `query.hash.replace` 错误.
thinkershare
2023-01-19 11:16:37 +08:00
一看就是你少发送了请求参数,这个服务器后端估计用的是 nodeJS,然后它们将服务器错误返回给你前端(这是大忌)。把代码贴出来。另外你为了确定发送的请求是否一样,可以直接抓包嘛,对比一下两次请求的 HTTP 请求消息,一下就知道发送报文的差别了。
thinkershare
2023-01-19 11:17:24 +08:00
HTTPS 抓包办法网上搜一下,很容易搞定。
samohyes
2023-01-19 11:19:57 +08:00
@FaiChou
感谢回复。浏览器返回头信息如下

```
access-control-allow-headers: X-Requested-With
access-control-allow-methods: PUT,POST,GET,DELETE,OPTIONS,GZIP
access-control-allow-origin: *
alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400
cf-cache-status: DYNAMIC
cf-ray: 78bc38162ba77c41-LAX
content-encoding: br
content-type: application/json; charset=utf-8
date: Thu, 19 Jan 2023 02:42:49 GMT
etag: W/"33-jQyycVIXHHaApQyPK1PD9fntp1s"
nel: {"success_fraction":0,"report_to":"cf-nel","max_age":604800}
report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=dfOHoNO9%2FpYnQxDBsTkw%2FkWGSMiRClKfpHSHnOgWd%2BCoerBw4F9RX3qrFX8cYZq54OxLb1PPHrISmNF7Mu%2B8Wq0yGJ2VIMfOS2WlaH%2BgvbZ5IInUdKHsA%2BsL9MBPwc5ziXRviwnFS0k%3D"}],"group":"cf-nel","max_age":604800}
server: cloudflare
strict-transport-security: max-age=15552000; includeSubDomains; preload
x-content-type-options: nosniff
x-powered-by: Express
```
返回的内容就是正确的。
{"msg":"Success","info":"****"}


我 python 代码里面打印了下 headers 如下
```
{'Date': 'Thu, 19 Jan 2023 03:17:37 GMT', 'Content-Type': 'text/html; charset=utf-8', 'Transfer-Encoding': 'chunked', 'Connection': 'keep-alive', 'X-Powered-By': 'Express', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'X-Requested-With', 'Access-Control-Allow-Methods': 'PUT,POST,GET,DELETE,OPTIONS,GZIP', 'Content-Security-Policy': "default-src 'none'", 'X-Content-Type-Options': 'nosniff', 'CF-Cache-Status': 'DYNAMIC', 'Report-To': '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v3?s=UUnds37Eb6mJ4xILaRJ30Y7xJ7F4bS4ggK4Vm2yRmzMa0pE69p9sOg%2FRWNMtH1bm3mVmtHe43r%2F14ZyCdkCNZzvqgcLA114qEZCgRGTlJRiCLGWOO16mEiAWtfQAUccuzTwstx5Bv8I%3D"}],"group":"cf-nel","max_age":604800}', 'NEL': '{"success_fraction":0,"report_to":"cf-nel","max_age":604800}', 'Strict-Transport-Security': 'max-age=15552000; includeSubDomains; preload', 'Server': 'cloudflare', 'CF-RAY': '78bc6b17eb1f20b1-IAD', 'alt-svc': 'h3=":443"; ma=86400, h3-29=":443"; ma=86400'}
```
这个意思是我请求成功了?只是说没办法解析?
samohyes
2023-01-19 11:22:44 +08:00
@thinkershare

```
headers = {
'authority': 'https://st.org',
'accept': '*/*',
'accept-language': 'en,zh;q=0.9,zh-CN;q=0.8,en-US;q=0.7,en-GB;q=0.6',
'origin': 'https://st.org',
'referer': 'https://st.org',
'sec-ch-ua': '"Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'sec-fetch-dest': 'empty',
'sec-fetch-site': 'same-site',
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36',
}

params = {
'test': 1
}

s = requests.Session()

response = s.get('https://***', params=params, headers=headers)

print(response.headers)
```

我的 python 代码,我直接 f12 看到的那个 api 请求,然后 copy as cmd 过来的,请求参数应该是没有漏的吧。
thinkershare
2023-01-19 11:25:10 +08:00
@samohyes 请求失败了,正常应该返回 application/json, 你现在返回了 text/html(就是错误页面)。
thinkershare
2023-01-19 11:27:23 +08:00
@samohyes 你将浏览器发送的 GET 请求的网站 URL(带有查询参数的),作为 GET 的第一个参数,不要 params
samohyes
2023-01-19 11:32:15 +08:00
@thinkershare 成了!!! 感谢老哥相助!!!
NouveauNom
2023-01-19 11:32:25 +08:00
https://www.scrapingbee.com/curl-converter/python/ 把 curl 复制到里面用和这个工具转下试试
FaiChou
2023-01-19 11:34:49 +08:00
建议先使用 Paw 或者 Postman 这种工具做下测试, 用 curl 也行. 你用 copy as fetch 会有一大堆额外的附加信息, 先简化下, 保留重要的请求数据, 比如 referer/UA/body/ 等
samohyes
2023-01-19 11:37:59 +08:00
@NouveauNom 感谢,是 copy as fetch 多了个那个 param 导致出错了。。汗。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/909842

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX