繁体   English   中英

无法使用请求从网页中抓取名称

[英]Unable to scrape a name from a webpage using requests

我已经在python中创建了一个脚本来获取一个名称,该名称在填写网页输入时填充。 打开该网页后,您将获得该名称->(在下面提供了网站链接),在CP Number旁边放置16803 ,然后点击搜索按钮。

我知道如何使用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编码POST数据的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标头,就可以使用datafiles获得有效的响应。

无需添加任何额外的标题。 使用Session对象时,默认情况下会存储和提交cookie。 Content-Type标头是自动创建的-使用data参数时使用“ application / x-www-form-urlencoded”,使用files “ multipart / form-data”。 不需要更改默认的用户代理或添加引荐来源网址。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM