Очистить .aspx форму с Python - PullRequest
       7

Очистить .aspx форму с Python

0 голосов
/ 28 февраля 2019

Я пытаюсь почистить: 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)

Когда я печатаю объект response.contents, я получаюэто сообщение (tl; dr, оно говорит, что «Произошла системная ошибка. Система оповестит службу технической поддержки о проблеме» * ):

b'\r\n\r\n<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\r\n\r\n<html xmlns="http://www.w3.org/1999/xhtml" >\r\n<head><title>\r\n\r\n</title></head>\r\n<body>\r\n   <form name="form1" method="post" action="Error.aspx?ErrorID=86e0c980-7832-4fc5-b5a8-a8254dd8ad69" id="form1">\r\n<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTg3NjI4NzkzNmRkaCA5IA9393/t2iMAptLYU1QiPc8=" />\r\n\r\n<input type="hidden" name="__VIEWSTATEGENERATOR" id="__VIEWSTATEGENERATOR" value="9D6BDE45" />\r\n    <div>\r\n        <h4>\r\n            <span id="lblError">Error</span>\r\n        </h4>\r\n        <span id="lblMessage" class="Validator"><font color="Black">System error occurred. The system will alert technical support of the problem.</font></span>\r\n    </div>\r\n    </form>\r\n</body>\r\n</html>\r\n'

Я использовал другие опции, например, изменениеаргумент __EVENTTARGET, как предлагается здесь , а также передать cookie от первого запроса до запроса POST.Проверяя источник страницы, я заметил, что форма имеет функцию «запроса», для работы которой нужны __EVENTTARGET и __EVENTARGUMENT:

//<![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();
    }
}
//]]>

Но оба аргумента пусты (как можно проверитьв инспекторе разработчиков Chrome) в теле ответа POST.Другая проблема заключается в том, что мне нужно либо загрузить файл в любом из форматов (PDF или Excel), либо получить версию HTML, но форма .ASPX не отображает информацию на той же странице, она открывает новый URL: https://apps.neb -one.gc.ca / CommodityStatistics / ViewReport.aspx с информацией вместо.

Я здесь немного потерялся, чего мне не хватает?

1 Ответ

0 голосов
/ 02 марта 2019

Мне удалось успешно решить эту проблему, обрабатывая значения __VIEWSTATE с большей осторожностью.В форме ASPX страница использует __VIEWSTATE для хеширования статуса веб-страницы (т. Е. Какие параметры формы уже выбран пользователем или в нашем случае запрошено) и разрешают следующий запрос.

В этом случае:

  1. Запросить получение всех заголовков, сохраните их в payload и добавьте мой первый выбор, обновив словарь.
  2. Сделайте второй запрос с обновленным значением __VIEWSTATE и добавьте дополнительные параметры в мой запрос.
  3. То же, что и 2., но с добавлением последней опции.

У меня будет пять одинаковых HTML-текстов, которые я получаю, когда делаю запрос с помощью браузера, но все равно не показывает мне данные или не позволяет мне загружать файлы как часть телапоследний запрос.Эту проблему можно решить с помощью selenium, но я не добился успеха. Этот вопрос в SO описывает мою проблему.

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)
...