【问题标题】:Get contents of website from QWebView using Qt 5.5.1使用 Qt 5.5.1 从 QWebView 获取网站内容
【发布时间】:2017-02-13 10:50:46
【问题描述】:

我正在使用 Qt 5.5.1,我使用 QWebview 制作了一个小型浏览器,当我打开一个网页并按下一个按钮时,它会获取网站的内容,就像我在 QnetworkAccessManager 中使用 get 方法一样使用它是因为我想从具有登录页面的网站获取数据,因此当我登录时 URL 不会更改,并且没有将方法发布到 PHP 以获取数据。
例如,当我登录 www.login.com 时,登录数据显示在同一链接上
我需要任何可以解决此问题的想法,或者是否可以从 QWebview 中打开的网站获取当前数据
注意
当我登录网站并通过在 Firefox 中按查看源代码从中获取数据时,登录数据会出现在源代码中
这是我尝试过的

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {
        ui->setupUi(this);
        ui->webView->load(QUrl("https://www.login.com")); // load page that have user name and password field
        QWebPage *page = ui->webView->page(); // get the current page 
        manager = page->networkAccessManager(); // get the access manager from this page
    }

    MainWindow::~MainWindow() {
        delete ui;
    }
    // get button
    void MainWindow::on_pushButton_clicked() {
        reply = manager->get(QNetworkRequest(QUrl("https://www.login.com"))); // make get now after login
        connect(reply, SIGNAL(readyRead()),this,SLOT(readyRead()));
        connect(reply, SIGNAL(finished()),this, SLOT(finish()));
    }

    void MainWindow::readyRead() {
        QString str = QString::fromUtf8(reply->readAll()).trimmed(); // read the data
        ui->plainTextEdit->appendPlainText(str);
    }

但我在没有登录的情况下获得了第一页的数据。我想在登录后获取页面内容,请给我任何提示我应该做什么。
更新
我从firefox查看页面源代码获取文本输入名称并使用QUrlQuery对其进行发布,结果是没有登录的第一页这是HTML代码的一部分我得到了它的名称

<label class="label-off" for="dwfrm_ordersignup_orderNo">Numéro de la commande</label> <input class="textinput required" id="anyname" type="text"  name="UserName"  value=""  maxlength="2147483647" placeholder="* UserName" data-missing-error="Saisis ton numéro de commande. "  data-parse-error="Ce contenu est invalide"  data-range-error="Ce contenu est trop long ou trop court"  required="required" />

其他字段的代码相同。
我在 Qt 中用于发帖的代码

manager = new QNetworkAccessManager(this);
QUrlQuery query;
query.addQueryItem("UserName", "AAAA");
query.addQueryItem("Password", "BBB");
reply = manager->post(QNetworkRequest(QUrl(ui->lineEdit->text().trimmed())), query.toString().toUtf8());
connect(reply,&QNetworkReply::downloadProgress,this,&MainWindow::progress);
connect(reply,SIGNAL(readyRead()),this,SLOT(readyRead()));
connect(reply, SIGNAL(finished()), this,SLOT(finish()));

我尝试使用我制作的 PHP 页面的帖子代码,它在这里解决了问题,它只是 HTML 页面

【问题讨论】:

  • 您可能想向服务器发送一个 post 方法,您需要分析登录页面并查看文本输入的名称并将其作为键传递给 QUrlQuery 并传递这些各自的值(通常是名称和密码)。 here 发布了如何使用 Qt 进行 post 方法的示例。
  • 我用我尝试过的方法更新了这个问题,请看看这个
  • 请看我的回答。

标签: html c++ qt qnetworkaccessmanager qnetworkreply


【解决方案1】:

我将使用不同的方法,而不是模拟 POST 请求,我将使用QWebView 正常加载登录页面,并使用 Qt 填写用户名、密码并假点击提交按钮。

关于如何保存登录后的页面,而不是 HTML 代码,Qt 提供的一个好方法是将 Web 视图呈现为 PDF,缺点是会丢失 HTML 代码。

如果代码足够你可以使用webview-&gt;page()-&gt;mainFrame()-&gt;toHtml()

看一个简单的例子,请注意代码需要适配自己的环境,分析登录页面等

void MainWindow::start()
{
    connect(webview, &QWebView::loadFinished, this, &MainWindow::LogIn);

    QString html = "<html>"
                   "<body>"
                   "<form action=\"https://httpbin.org/post\" method=\"POST\">"
                   "Username:<br>"
                   "<input type=\"text\" name=\"usernameinput\" value=\"abc\">"
                   "<br>"
                   "Password:<br>"
                   "<input type=\"password\" name=\"passwordinput\" value=\"123\">"
                   "<br><br>"
                   "<button name=\"button1\">Submit</button>"
                   "</form>"
                   "</body>"
                   "</html>";

    webview->setHtml(html); //Load yours https://www.login.com, using setHtml just for example
}

void MainWindow::LogIn(bool ok)
{
    disconnect(webview, &QWebView::loadFinished, this, &MainWindow::LogIn); //Disconnect the SIGNAL

    if (!ok)
        return;

    QWebElement document = webview->page()->mainFrame()->documentElement();

    QWebElement username = document.findFirst("input[name=usernameinput]"); //Find the first input with name=usernameinput

    if (username.isNull())
        return;

    username.setAttribute("value", "def"); //Change the value of the usernameinput input even
                                           //if it already has some value

    QWebElement password = document.findFirst("input[name=passwordinput]"); //Do the same for password

    if (password.isNull())
        return;

    password.setAttribute("value", "123456"); //Do the same for password

    QWebElement button = document.findFirst("button[name=button1]"); //Find the button with name "button1"

    if (button.isNull())
        return;

    connect(webview, &QWebView::loadFinished, this, &MainWindow::finished);

    button.evaluateJavaScript("this.click()"); //Do a fake click on the submit button
}

void MainWindow::finished(bool ok)
{
    disconnect(webview, &QWebView::loadFinished, this, &MainWindow::finished);

    if (!ok)
        return;

    QByteArray data;
    QBuffer buffer(&data);

    if (!buffer.open(QIODevice::WriteOnly))
        return;

    QPdfWriter pdfwriter(&buffer);

    pdfwriter.setResolution(100); //In DPI

    webview->page()->setViewportSize(QSize(pdfwriter.width(), pdfwriter.height()));

    QPainter painter;
    painter.begin(&pdfwriter);
    webview->page()->mainFrame()->render(&painter);
    painter.end();

    buffer.close();

    qDebug() << "PDF Size:" << data.size(); //Now you have a PDF in memory stored on "data"
}

【讨论】:

  • 非常感谢您的回复和您的努力 我很感激我尝试了这段代码,但它制作了一个 pdf 文件,其中包含登录页面,其中写入了用户名和密码的字段 未按下单击按钮!我检查了源代码,发现提交按钮的类型不是 而是
  • 现在有什么方法可以让按钮像您一样在代码中单击?可能是因为提交的类型不是 而它是
  • 是的,这取决于对象,如果它有type=submit,或者是一个按钮,一个超链接等。您需要在页面上找到对象的唯一标识符并将其传递给@ 987654324@。我已经编辑了我的答案,以显示按钮具有 name=button1 的示例。
  • @AntonioDias 我可以在 Qt Quick Application 中使用它吗? QWebView 类和 QWebElement 和 ... ?
  • @mohsen:我没有找到办法做到这一点,也许可以,也许不可以,我不确定!请注意,OP 问题是关于 C++ 而不是 QML!
猜你喜欢
  • 2013-10-30
  • 2011-01-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
  • 2014-07-31
相关资源
最近更新 更多