V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
samohyes
V2EX  ›  程序员

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

  •  
  •   samohyes · 2023-01-19 11:06:06 +08:00 · 1491 次点击
    这是一个创建于 673 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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
    

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

    11 条回复    2023-01-19 11:37:59 +08:00
    FaiChou
        1
    FaiChou  
       2023-01-19 11:14:40 +08:00   ❤️ 1
    返回的头信息是什么? 感觉这是正常返回了 html, 但你的 python 环境没有 js 引擎, 所以会报一个 `query.hash.replace` 错误.
    thinkershare
        2
    thinkershare  
       2023-01-19 11:16:37 +08:00
    一看就是你少发送了请求参数,这个服务器后端估计用的是 nodeJS,然后它们将服务器错误返回给你前端(这是大忌)。把代码贴出来。另外你为了确定发送的请求是否一样,可以直接抓包嘛,对比一下两次请求的 HTTP 请求消息,一下就知道发送报文的差别了。
    thinkershare
        3
    thinkershare  
       2023-01-19 11:17:24 +08:00
    HTTPS 抓包办法网上搜一下,很容易搞定。
    samohyes
        4
    samohyes  
    OP
       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
        5
    samohyes  
    OP
       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
        6
    thinkershare  
       2023-01-19 11:25:10 +08:00
    @samohyes 请求失败了,正常应该返回 application/json, 你现在返回了 text/html(就是错误页面)。
    thinkershare
        7
    thinkershare  
       2023-01-19 11:27:23 +08:00   ❤️ 1
    @samohyes 你将浏览器发送的 GET 请求的网站 URL(带有查询参数的),作为 GET 的第一个参数,不要 params
    samohyes
        8
    samohyes  
    OP
       2023-01-19 11:32:15 +08:00
    @thinkershare 成了!!! 感谢老哥相助!!!
    NouveauNom
        9
    NouveauNom  
       2023-01-19 11:32:25 +08:00
    https://www.scrapingbee.com/curl-converter/python/ 把 curl 复制到里面用和这个工具转下试试
    FaiChou
        10
    FaiChou  
       2023-01-19 11:34:49 +08:00
    建议先使用 Paw 或者 Postman 这种工具做下测试, 用 curl 也行. 你用 copy as fetch 会有一大堆额外的附加信息, 先简化下, 保留重要的请求数据, 比如 referer/UA/body/ 等
    samohyes
        11
    samohyes  
    OP
       2023-01-19 11:37:59 +08:00
    @NouveauNom 感谢,是 copy as fetch 多了个那个 param 导致出错了。。汗。。。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2546 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 01:43 · PVG 09:43 · LAX 17:43 · JFK 20:43
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.