这篇文章将给大家演示QT网络编程在HTTP中的应用,用来爬取网页内容或者下载文件.我用过在三种语言是来爬取网页内容,用C语言我写了100行代码,用C++写10行代码,用Python写了两行代码.大家从这个可以看出编程的效率,但是同时带来一个问题,程序的运行效率是C>--C++>--Python .
HTTP在C++中有一个QtNetwork类,最常用的两个函数是QNetworkAccessManager和QNetworkReply.在代码中可以post参数,可以设置代理,本文只实现了网页的下载,其他内容大家可以参考帮助文档,学习QT应该学会看QT Assistant.
新建一个Qt Gui应用,项目名称为myHTTP.其他保持默认即可,在工程文件中添加QT += network表示支持网络库
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QUrl>
#include <QFile>
#include <QTextStream>
class QFile;
class QNetworkReply;
class QNetworkAccessManager;
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void startRequest(QUrl url);
void SaveFile(QString string,QString path)
{
QFile file(path);
if(!file.open(QIODevice::WriteOnly | QIODevice::Append)) return ;
QTextStream out(&file);
out << string <<endl;
file.close();
}
private slots:
void httpFinished();
void httpReadyRead();
void updateDataReadProgress(qint64, qint64);
void on_pushButton_clicked();
private:
Ui::MainWindow *ui;
QNetworkAccessManager *manager;
QNetworkReply *reply;
QUrl url;
QFile *file;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QtNetwork>
#include <QTextCodec>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
manager = new QNetworkAccessManager(this);
ui->progressBar->hide();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::startRequest(QUrl url)
{
reply = manager->get(QNetworkRequest(url));
connect(reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead()));
connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
this, SLOT(updateDataReadProgress(qint64,qint64)));
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
}
void MainWindow::httpReadyRead()
{
/* 不能调用两次reply->readAll(),第二次就会读取的数据为空 */
//if (file) file->write(reply->readAll());
QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QString string = ui->lineEdit_2->text();
QString all = codec->toUnicode(reply->readAll());
SaveFile(all,string);
}
void MainWindow::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}
void MainWindow::httpFinished()
{
ui->progressBar->hide();
file->flush();
file->close();
reply->deleteLater();
reply = 0;
delete file;
file = 0;
}
void MainWindow::on_pushButton_clicked()
{
url = ui->lineEdit->text();
QFileInfo info(url.path());
qDebug() << "url.path()=" << url.path();
QString fileName(info.fileName());
if (fileName.isEmpty())
{
fileName = "index.html";
qDebug() << "File Name is Empty!,default filename is index.html";
}
file = new QFile(fileName);
if(!file->open(QIODevice::WriteOnly))
{
qDebug() << "file open error";
delete file;
file = 0;
return;
}
startRequest(url);
ui->progressBar->setValue(0);
ui->progressBar->show();
}
main.cpp就不用贴了吧,默认即可,就是创建了一个MainWindow的对象,然后显示MainWindow.show(),然后爬取的内容就以html格式保存到工程路径下面了,大家可以指定路径的.
mainwindow.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralWidget">
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>30</x>
<y>40</y>
<width>101</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>下载URL地址:</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit">
<property name="geometry">
<rect>
<x>30</x>
<y>70</y>
<width>321</width>
<height>31</height>
</rect>
</property>
</widget>
<widget class="QProgressBar" name="progressBar">
<property name="geometry">
<rect>
<x>30</x>
<y>120</y>
<width>361</width>
<height>22</height>
</rect>
</property>
<property name="value">
<number>24</number>
</property>
</widget>
<widget class="QPushButton" name="pushButton">
<property name="geometry">
<rect>
<x>320</x>
<y>180</y>
<width>51</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>下载</string>
</property>
</widget>
<widget class="QLineEdit" name="lineEdit_2">
<property name="geometry">
<rect>
<x>70</x>
<y>181</y>
<width>251</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>/home/linux/Linux_Google.html</string>
</property>
</widget>
<widget class="QLabel" name="label_2">
<property name="geometry">
<rect>
<x>10</x>
<y>181</y>
<width>51</width>
<height>31</height>
</rect>
</property>
<property name="text">
<string>文件路径</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menuBar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QToolBar" name="mainToolBar">
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
<widget class="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>
程序运行效果如下:
大家可以在上面代码中添加代理和post参数,我就不每个都做测试了.
文章出自:Linux_Google