【问题标题】:How to get the web page using requests.post?如何使用 requests.post 获取网页?
【发布时间】:2018-11-22 10:45:26
【问题描述】:

我想得到网页http://www3.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx输入股票代码为5的结果。

问题是我在按搜索后不知道该网站,因为它运行的是 javascript。

此外,如何找到需要传递给requests.post的参数,例如数据?需要标头吗?

【问题讨论】:

  • 您想模拟在“股票代码”字段输入5并按“搜索”后发送的POST请求吗?
  • 是的,你是对的。
  • 点击搜索时看起来网站有问题
  • 网站正常运行。在股票代码字段输入5后,然后按search,即可查看显示结果的页面。
  • 谁能帮忙?

标签: python web-scraping python-requests


【解决方案1】:

您有多种选择:

1) 您可以使用 Selenium。首先安装 Selenium。

sudo pip3 install selenium

然后获取驱动程序https://sites.google.com/a/chromium.org/chromedriver/downloads(根据您的操作系统,您可能需要指定驱动程序的位置)

from selenium import webdriver
from bs4 import BeautifulSoup
import time

browser = webdriver.Chrome()
url = "http://www3.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx"
browser.get(url)
element = browser.find_element_by_id('ctl00_txt_stock_code')  # find the text box
time.sleep(2)
element.send_keys('5')  # populate the text box
time.sleep(2)
element.submit()  # submit the form
soup = BeautifulSoup(browser.page_source, 'html.parser')
browser.quit()
for news in soup.find_all(class_='news'):
    print(news.text)

2) 或者将 PyQt 与 QWebEngineView 一起使用。

在 Ubuntu 上安装 PyQt:

    sudo apt-get install python3-pyqt5
    sudo apt-get install python3-pyqt5.qtwebengine

或在其他操作系统(64 位版本的 Python)上

    pip3 install PyQt5

基本上,您在打开表单时加载第一页。通过运行 JavaScript 填写表单,然后提交。 loadFinished() 信号被调用了两次,第二次是因为您提交了表单,因此您可以使用 if 语句来区分调用。

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from bs4 import BeautifulSoup


class Render(QWebEngineView):
    def __init__(self, url):
        self.html = None
        self.first_pass = True
        self.app = QApplication(sys.argv)
        QWebEngineView.__init__(self)
        self.loadFinished.connect(self._load_finished)
        self.load(QUrl(url))
        self.app.exec_()

    def _load_finished(self, result):
        if self.first_pass:
            self._first_finished()
            self.first_pass = False
        else:
            self._second_finished()

    def _first_finished(self):
        self.page().runJavaScript("document.getElementById('ctl00_txt_stock_code').value = '5';")
        self.page().runJavaScript("document.getElementById('ctl00_sel_DateOfReleaseFrom_y').value='1999';")
        self.page().runJavaScript("preprocessMainForm();")
        self.page().runJavaScript("document.forms[0].submit();")

    def _second_finished(self):
        self.page().toHtml(self.callable)

    def callable(self, data):
        self.html = data
        self.app.quit()

url = "http://www3.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx"
web = Render(url)
soup = BeautifulSoup(web.html, 'html.parser')
for news in soup.find_all(class_ = 'news'):
    print(news.text)

输出:

Voting Rights and Capital
Next Day Disclosure Return
NOTICE OF REDEMPTION AND CANCELLATION OF LISTING
THIRD INTERIM DIVIDEND FOR 2018
Notification of Transactions by Persons Discharging Managerial Responsibilities
Next Day Disclosure Return
THIRD INTERIM DIVIDEND FOR 2018
Monthly Return of Equity Issuer on Movements in Securities for the month ended 31 October 2018
Voting Rights and Capital
PUBLICATION OF BASE PROSPECTUS SUPPLEMENT
3Q 2018 EARNINGS RELEASE AUDIO WEBCAST AND CONFERENCE CALL
3Q EARNINGS RELEASE - HIGHLIGHTS
Scrip Dividend Circular
2018 Third Interim Dividend; Scrip Dividend
THIRD INTERIM DIVIDEND FOR 2018 SCRIP DIVIDEND ALTERNATIVE
NOTIFICATION OF MAJOR HOLDINGS
EARNINGS RELEASE FOR THIRD QUARTER 2018
NOTIFICATION OF MAJOR HOLDINGS
Monthly Return of Equity Issuer on Movements in Securities for the month ended 30 September 2018
THIRD INTERIM DIVIDEND FOR 2018; DIVIDEND ON PREFERENCE SHARES

您也可以使用 Scrapy splash https://github.com/scrapy-plugins/scrapy-splash

或请求-HTML https://html.python-requests.org/

但我不确定您将如何使用最后两种方法填写表格。

更新了如何阅读下一页:

import sys
from PyQt5.QtWidgets import QApplication
from PyQt5.QtCore import QUrl
from PyQt5.QtWebEngineWidgets import QWebEngineView
from bs4 import BeautifulSoup


class Render(QWebEngineView):
    def __init__(self, url):
    self.html = None
    self.count = 0
    self.first_pass = True
    self.app = QApplication(sys.argv)
    QWebEngineView.__init__(self)
    self.loadFinished.connect(self._load_finished)
    self.load(QUrl(url))
    self.app.exec_()

    def _load_finished(self, result):
    if self.first_pass:
        self._first_finished()
        self.first_pass = False
    else:
        self._second_finished()

    def _first_finished(self):
    self.page().runJavaScript("document.getElementById('ctl00_txt_stock_code').value = '5';")
    self.page().runJavaScript("document.getElementById('ctl00_sel_DateOfReleaseFrom_y').value='1999';")
    self.page().runJavaScript("preprocessMainForm();")
    self.page().runJavaScript("document.forms[0].submit();")

    def _second_finished(self):
    try:
        self.page().toHtml(self.parse)
        self.count += 1
        if self.count > 5:
             self.page().toHtml(self.callable)
        else:
            self.page().runJavaScript("document.getElementById('ctl00_btnNext2').click();")
    except:
        self.page().toHtml(self.callable)

    def parse(self, data):
    soup = BeautifulSoup(data, 'html.parser')
    for news in soup.find_all(class_ = 'news'):
        print(news.text)

    def callable(self, data):
    self.app.quit()

url = "http://www3.hkexnews.hk/listedco/listconews/advancedsearch/search_active_main.aspx"
web = Render(url)

【讨论】:

  • 谢谢你,丹。硒可以解决这个问题。但我想知道如何使用requests 处理像这样的javascript 网页。还有其他更快的选择吗?
  • 这个特定的网页有一个由 JavaScript 生成的 VIEWSTATE 令牌和一个由 JavaScript 生成的加密版本。如果不实际运行 JavaScript,几乎不可能重新创建这些令牌。没有办法对请求执行此操作,我不确定您将如何使用 Requests-HTML 运行 require JavaScript。如果您不喜欢 Selenium 选项,请尝试我在答案中给出的 PyQt5 解决方案。
猜你喜欢
  • 2019-10-06
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 2021-11-26
  • 2020-10-16
  • 1970-01-01
  • 2018-03-01
  • 1970-01-01
相关资源
最近更新 更多