用Python创建Scrape.aspx表单

2024-10-04 05:29:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在试着整理:https://apps.neb-one.gc.ca/CommodityStatistics/Statistics.aspx,这在纸上看起来是一个简单的任务,并且有很多来自其他SO问题的资源。尽管如此,无论我如何更改请求,我都会得到相同的错误。在

我试过以下方法:

import requests
from bs4 import BeautifulSoup

url = "https://apps.neb-one.gc.ca/CommodityStatistics/Statistics.aspx"

with requests.Session() as s:
    s.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36'}

    response = s.get(url)
    soup = BeautifulSoup(response.content)

     data = {
         "ctl00$MainContent$rdoCommoditySystem": "ELEC",
         "ctl00$MainContent$lbReportName": "171",
         "ctl00$MainContent$ddlFrom": "01/11/2018 12:00:00 AM",
         "ctl00$MainContent$rdoReportFormat": "Excel",
         "ctl00$MainContent$btnView": "View",
         "__EVENTVALIDATION": soup.find('input', {'name':'__EVENTVALIDATION'}).get('value',''),
         "__VIEWSTATE": soup.find('input', {'name': '__VIEWSTATE'}).get('value', ''),
         "__VIEWSTATEGENERATOR": soup.find('input', {'name': '__VIEWSTATEGENERATOR'}).get('value', '')
     }

    response = requests.post(url, data=data)

太长了,读不下去了,当我打印^ {< CD1>}对象时,我得到了这个消息(TL;DR,它说 >系统错误发生了。系统将向技术支持人员发出问题“):

^{pr2}$

我还使用了其他选项,如修改__EVENTTARGET参数,如建议的here,并将cookie从第一个请求传递到POST请求。需要检查的是{cd2>的函数

//<![CDATA[
var theForm = document.forms['aspnetForm'];
if (!theForm) {
    theForm = document.aspnetForm;
}
function __doPostBack(eventTarget, eventArgument) {
    if (!theForm.onsubmit || (theForm.onsubmit() != false)) {
        theForm.__EVENTTARGET.value = eventTarget;
        theForm.__EVENTARGUMENT.value = eventArgument;
        theForm.submit();
    }
}
//]]>

但是两个参数在POST响应的主体中都是空的(可以在Chrome开发人员检查器中检查)。另一个问题是,我需要以任何格式(PDF或Excel)下载文件,或者获取HTML版本,但是.ASPX表单不会在同一页面中呈现信息,而是打开一个新的url:https://apps.neb-one.gc.ca/CommodityStatistics/ViewReport.aspx和信息。在

我有点迷路了,我错过了什么?在


Tags: appshttpsurlgetvalueonegcca
1条回答
网友
1楼 · 发布于 2024-10-04 05:29:16

通过更加小心地处理__VIEWSTATE值,我成功地解决了这个问题。在ASPX表单中,页面使用__VIEWSTATE来散列网页的状态(即用户已经选择了表单的哪些选项,或者在我们的例子中是请求的),并允许下一个请求。在

在这种情况下:

  1. 请求获取所有标题,将其存储在payload中,并通过更新字典添加我的第一个选择。在
  2. 使用更新的__VIEWSTATE值进行第二次请求,并在请求中添加更多选项。在
  3. 与2相同,但添加了最终选项。在

这将给我五个相同的HTML正文,当我使用浏览器提出我的请求,但仍然不显示我的数据,或允许我下载文件作为最后一个请求正文的一部分。这个问题可以用selenium来处理,但我没有成功。This问题请描述我的问题。在

url = 'https://apps.neb-one.gc.ca/CommodityStatistics/Statistics.aspx'

with requests.Session() as s:
        s.headers = {
            "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/40.0.2214.115 Safari/537.36",
            "Content-Type": "application/x-www-form-urlencoded",
            "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
            "Referer": "https://apps.neb-one.gc.ca/CommodityStatistics/Statistics.aspx",
            "Accept-Encoding": "gzip, deflate, br",
            "Accept-Language": "en-US,en;q=0.9"
        }

        response = s.get(url)
        soup = BeautifulSoup(response.content, 'html5lib')

        data = { tag['name']: tag['value'] 
            for tag in soup.select('input[name^=ctl00]') if tag.get('value')
            }
        state = { tag['name']: tag['value'] 
                for tag in soup.select('input[name^=__]')
            }

        payload = data.copy()
        payload.update(state)

        payload.update({
            "ctl00$MainContent$rdoCommoditySystem": "ELEC",
            "ctl00$MainContent$lbReportName": '76',
            "ctl00$MainContent$rdoReportFormat": 'PDF',
            "ctl00$MainContent$ddlStartYear": "2008",
            "__EVENTTARGET": "ctl00$MainContent$rdoCommoditySystem$2"
        })

        print(payload['__EVENTTARGET'])
        print(payload['__VIEWSTATE'][-20:])

        response = s.post(url, data=payload, allow_redirects=True)
        soup = BeautifulSoup(response.content, 'html5lib')

        state = { tag['name']: tag['value'] 
                 for tag in soup.select('input[name^=__]')
             }

        payload.pop("ctl00$MainContent$ddlStartYear")
        payload.update(state)
        payload.update({
            "__EVENTTARGET": "ctl00$MainContent$lbReportName",
            "ctl00$MainContent$lbReportName": "171",
            "ctl00$MainContent$ddlFrom": "01/12/2018 12:00:00 AM"
        })

        print(payload['__EVENTTARGET'])
        print(payload['__VIEWSTATE'][-20:])

        response = s.post(url, data=payload, allow_redirects=True)
        soup = BeautifulSoup(response.content, 'html5lib')

        state = { tag['name']: tag['value']
                 for tag in soup.select('input[name^=__]')
                }

        payload.update(state)
        payload.update({
            "ctl00$MainContent$ddlFrom": "01/10/1990 12:00:00 AM",
            "ctl00$MainContent$rdoReportFormat": "HTML",
            "ctl00$MainContent$btnView": "View"
        })

        print(payload['__VIEWSTATE'])

        response = s.post(url, data=payload, allow_redirects=True)
        print(response.text)

相关问题 更多 >