【问题标题】:No response for XHR request in python with requests.get()使用 requests.get() 在 python 中对 XHR 请求没有响应
【发布时间】:2020-03-28 16:08:47
【问题描述】:

我想从服务器上抓取german poll data。在这里,我搜索了一条示例街道,straße "Judengasse"。

我一直在尝试复制this。不幸的是,来自参考的链接不再完整,所以我无法直接将它与我的问题进行比较。由于我相当缺乏经验,我不知道重现通过 Web 界面提交的请求究竟需要什么。

我现在不知道我的请求需要标头的哪些属性才能工作,哪些属性可能是多余的。在 Chrome 的检查模式下,我发现在我的情况下,标头属性比引用的示例中的要多。

到目前为止,我的代码(不起作用)试图重现 SE 帖子:

import requests

url = 'https://online-service2.nuernberg.de/Finder/action/getItems'
data = {
    "finder":"Wahlraumfinder",
    "strasse":"Judengasse",
    "hausnummer":"0"
    }

headers = {
           'Host': 'online-service2.nuernberg.de', 
           'Referer': 'https://online-service2.nuernberg.de/Finder/?Wahlraumfinder', 
           'Accept': '*/*', 
           'Accept-Encoding': 'gzip, deflate, br', 
           'Accept-Language': 'de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7', 
           'Connection': 'keep-alive', 
           'Content-Length': '312', 
           'Content-Type': 'multipart/form-data; boundary=----WebKitFormBoundaryeJZfrnZATOw6B5By', 
           'DNT': '1', 
           'Host': 'online-service2.nuernberg.de', 
           'Referer': 'https://online-service2.nuernberg.de/Finder/?Wahlraumfinder', 
           'Sec-Fetch-Mode': 'cors', 
           'Sec-Fetch-Site': 'same-origin', 
           'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36',
           'X-Requested-With': 'XMLHttpRequest'
           }

response = requests.get(url, data=data, headers=headers)

我没有得到回应。我将所有请求标头添加到headers

不确定,是否需要更多标题。

此外,我不确定url 是否正确。

我希望为这个特定的请求“Judengasse”生成以下形式的输出:

Nr 0652
Wahllokal Willstätt.-Gym., Innerer Laufer Platz 11

这相当于在搜索栏中输入“Judengasse”并点击继续 搜索“Suche”并提取第一个输出框“Wahl-/Stimmbezirk”的部分

当我在 Chrome 的开发模式下查看 XHR 时:

常规

Request URL: https://online-service2.nuernberg.de/Finder/action/getItems
Request Method: POST
Status Code: 200 OK
Remote Address: 193.22.166.102:443
Referrer Policy: no-referrer-when-downgrade

响应标头

Connection: Keep-Alive
Content-Length: 1149
Content-Type: application/json;charset=UTF-8
Date: Wed, 04 Dec 2019 00:21:30 GMT
Keep-Alive: timeout=5, max=100
Server: Apache

请求标头

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7
Connection: keep-alive
Content-Length: 312
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryx2jHYJHo3ejnKw0l
DNT: 1
Host: online-service2.nuernberg.de
Origin: https://online-service2.nuernberg.de
Referer: https://online-service2.nuernberg.de/Finder/?Wahlraumfinder
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-origin
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
X-Requested-With: XMLHttpRequest

来自数据

------WebKitFormBoundaryx2jHYJHo3ejnKw0l
Content-Disposition: form-data; name="action"

"action/getItems"
------WebKitFormBoundaryx2jHYJHo3ejnKw0l
Content-Disposition: form-data; name="data"

{"finder":"Wahlraumfinder","strasse":"Judengasse","hausnummer":"0"}
------WebKitFormBoundaryx2jHYJHo3ejnKw0l--

感谢您的阅读。

【问题讨论】:

    标签: ajax python-3.x python-requests xmlhttprequest


    【解决方案1】:

    经过一番研究,我终于设法从该服务器获得了 200 响应。

    首先,在这种情况下,requests.get 应替换为 requests.post,因为根据您从 Chrome 的开发模式“常规”部分获得的信息,您想要复制 HTTP POST 请求。

    其次,从标头中我们可以看到数据是作为“multipart/form-data”类型的请求发送的。据我了解,这是一种用于发送文件而不是常规数据的请求(更多关于这种类型的请求here)。

    所以,我将通过 POST 请求发送的字符串转换为二进制(这是通过预先添加 b 实现的)并将其传递给请求的 files 参数。出于某种原因,此参数需要在集合 {c} 内有一个元组 (a, b),因此是 {(None, data)}

    我还将街道名称作为参数传递给data,因此更容易操作它。

    我得到了这个工作代码(我正在使用浏览器的请求):

    import requests
    
    url = 'https://online-service2.nuernberg.de/Finder/action/getItems'
    
    street = b'Judengasse'
    
    data = b'-----------------------------15242581323522\r\n' \
           b'Content-Disposition: form-data; name=\"action\"\r\n\r\n' \
           b'\"action/getItems\"\r\n-----------------------------15242581323522\r\n' \
           b'Content-Disposition: form-data; name="data"\r\n\r\n' \
           b'{\"finder\":\"Wahlraumfinder\",\"strasse\":\"%s\",\"hausnummer\":\"0\"}\r\n' \
           b'-----------------------------15242581323522--' % street
    
    headers = {"Host": "online-service2.nuernberg.de",
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0",
                "Accept": "*/*",
                "Accept-Language": "en-US,en;q=0.5",
                "Accept-Encoding": "gzip, deflate, br",
                "X-Requested-With": "XMLHttpRequest",
                "Content-Type": "multipart/form-data; boundary=---------------------------15242581323522",
                "Content-Length": "321",
                "Origin": "https://online-service2.nuernberg.de",
                "DNT": "1",
                "Connection": "keep-alive",
                "Referer": "https://online-service2.nuernberg.de/Finder/?Wahlraumfinder",
               }
    
    
    multipart_data = {(None, data,)}
    response = requests.post(url, files=multipart_data, headers=headers)
    
    print(response.text)
    

    我收到了这个原始回复:

    {"id":"8c4f7a57-1bd6-423a-8ab8-e1e40e1e3852","items":[{"zeilenbeschriftung":"Wahl-/Stimmbezirk","linkAdr":null,"mapUrl":"http://online-service.nuernberg.de/Themenstadtplan/sta_gebietsgli
    ederungen.aspx?p_urlvislayer=Stimmbezirke&XKoord=4433503.05&YKoord=5480253.301&Zaehler=1&Textzusatz=Judengasse+0&z_XKoord=4433670.0&z_YKoord=5480347.0&z_Zaehler=1&z_Textzusatz=Wahllokal%
    20Willst%E4tt.-Gym.%2C+Innerer+Laufer+Platz+11","items":["0652","Judengasse, Neue Gasse","Willstätt.-Gym., Innerer Laufer Platz 11","Zi. 101 ,1. OG",null]},{"zeilenbeschriftung":"Stimmkr
    eis Landtagswahl","linkAdr":null,"mapUrl":"http://online-service.nuernberg.de/Themenstadtplan/sta_gebietsgliederungen.aspx?p_urlvislayer=Stimmkreis_LTW&XKoord=4433503.05&YKoord=5480253.3
    01&Zaehler=1&Textzusatz=Judengasse+0&p_scale=100000","items":["501","Nürnberg-Nord"]},{"zeilenbeschriftung":"Wahlkreis Bundestagswahl","linkAdr":null,"mapUrl":"http://online-service.nuer
    nberg.de/Themenstadtplan/sta_gebietsgliederungen.aspx?p_urlvislayer=Wahlkreis_BTW&XKoord=4433503.05&YKoord=5480253.301&Zaehler=1&Textzusatz=Judengasse+0&p_scale=150000","items":["244","N
    ürnberg-Nord"]}],"status":200}
    
    

    你可以很容易地解析得到你期望的结果:

    print(response.json()["items"][0]["items"])
    

    让步……

    ['0652', 'Judengasse, Neue Gasse', 'Willstätt.-Gym., Innerer Laufer Platz 11', 'Zi. 101 ,1. OG', None]
    
    

    希望对你有帮助。

    问候

    【讨论】:

    • 你可以像这样传递它们:street = bytes("äöüa", encoding="utf-8")。如果它不起作用,请告诉我。
    • 您是如何知道以二进制形式传递数据的?
    • 如果一开始你的意思是在多部分docs:“正如Content-Transfer-Encoding字段的定义中所说,除了“7bit”、“8bit”之外没有其他编码,或者“多部分”类型的实体允许使用“二进制”。“
    猜你喜欢
    • 2020-03-30
    • 2016-03-30
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多