我在python中创建了一个脚本来获取一个名称,该名称在填写网页中的输入时填充。以下是如何获得该名称 - >打开该网页后(下面给出了附加链接),将16803
放在CP Number
旁边,点击搜索按钮。
我知道如何使用selenium
抓住它,但我不想去那条路。我正在尝试使用requests
模块收集名称。我试图模仿我的脚本中的步骤(我在chrome开发工具中可以看到的)关于如何将请求发送到该站点的步骤。在payload
参数中我唯一无法自动提供的是ScrollTop
。
这是我的尝试:
import requests
from bs4 import BeautifulSoup
URL = "https://www.icsi.in/student/Members/MemberSearch.aspx"
with requests.Session() as s:
r = s.get(URL)
cookie_item = "; ".join([str(x)+"="+str(y) for x,y in r.cookies.items()])
soup = BeautifulSoup(r.text,"lxml")
payload = {
'StylesheetManager_TSSM':soup.select_one("#StylesheetManager_TSSM")['value'],
'ScriptManager_TSM':soup.select_one("#ScriptManager_TSM")['value'],
'__VIEWSTATE':soup.select_one("#__VIEWSTATE")['value'],
'__VIEWSTATEGENERATOR':soup.select_one("#__VIEWSTATEGENERATOR")['value'],
'__EVENTVALIDATION':soup.select_one("#__EVENTVALIDATION")['value'],
'dnn$ctlHeader$dnnSearch$Search':soup.select_one("#dnn_ctlHeader_dnnSearch_SiteRadioButton")['value'],
'dnn$ctr410$MemberSearch$ddlMemberType':0,
'dnn$ctr410$MemberSearch$txtCpNumber': 16803,
'ScrollTop': 474,
'__dnnVariable': soup.select_one("#__dnnVariable")['value'],
}
headers = {
'Content-Type':'multipart/form-data; boundary=----WebKitFormBoundaryBhsR9ScAvNQ1o5ks',
'Referer': 'https://www.icsi.in/student/Members/MemberSearch.aspx',
'Cookie':cookie_item,
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'
}
res = s.post(URL,data=payload,headers=headers)
soup_obj = BeautifulSoup(res.text,"lxml")
name = soup_obj.select_one(".name_head > span").text
print(name)
当我执行上面的脚本时,我收到以下错误:
AttributeError: 'NoneType' object has no attribute 'text'
如何在使用请求填写网页中的输入时获取填充的名称?
您的代码的主要问题是数据编码。我注意到您已将Content-Type标头设置为“multipart / form-data”,但这还不足以创建多部分编码数据。实际上,这是一个问题,因为实际的编码是不同的,因为您使用的是对URL数据进行URL编码的data
参数。要创建多部分编码数据,您应该使用files
参数。
您可以通过将额外的伪参数传递给files
来做到这一点,
res = s.post(URL, data=payload, files={'file':''})
(这将改变所有POST数据的编码,而不仅仅是'file'
字段)
或者,您可以将payload
字典中的值转换为元组,这是使用请求发布文件时的预期结构。
payload = {k:(None, str(v)) for k,v in payload.items()}
第一个值是文件名;在这种情况下不需要它所以我把它设置为None
。
接下来,您的POST数据应包含为获得有效响应所需的__EVENTTARGET
值。 (在创建POST数据字典时,提交服务器期望的所有数据非常重要。我们可以从浏览器获取数据:通过检查HTML表单或检查网络流量。)完整的代码,
import requests
from bs4 import BeautifulSoup
URL = "https://www.icsi.in/student/Members/MemberSearch.aspx"
with requests.Session() as s:
r = s.get(URL)
soup = BeautifulSoup(r.text,"lxml")
payload = {i['name']: i.get('value', '') for i in soup.select('input[name]')}
payload['dnn$ctr410$MemberSearch$txtCpNumber'] = 16803
payload["__EVENTTARGET"] = 'dnn$ctr410$MemberSearch$btnSearch'
payload = {k:(None, str(v)) for k,v in payload.items()}
r = s.post(URL, files=payload)
soup_obj = BeautifulSoup(r.text,"lxml")
name = soup_obj.select_one(".name_head > span").text
print(name)
经过一些测试,我发现服务器也接受URL编码的数据(可能是因为没有发布文件)。因此,如果您不更改默认的Content-Type标头,则可以使用data
或files
获得有效响应。
没有必要添加任何额外的标头。使用Session
对象时,默认情况下会存储和提交Cookie。当使用data
参数时,自动创建Content-Type标头 - “application / x-www-form-urlencoded”,使用files
使用“multipart / form-data”。不需要更改默认User-Agent或添加Referer。