从高中到大学,一直在固定小说网中下载小说,小说网停机过好几次但最后又起死回生。最近萌发一个想法,把小说网里的小说都爬下来。。

既然要爬网站肯定要对网站结构十分了解,幸好小说网没有弄什么登陆防爬措施,结构还是很简单的。

几个分类,各个分类下按页以时间排序

获取小说详细页地址其实很简单,利用正则表达式即可获得。

<div class="s">作者:<a href="/Writer/22265.html" target="_blank">星殒落</a><br />大小:5.3MB<br>等级:<em class="lstar3"></em><br>更新:2017-07-12</div><a href="/35942.html"><img src="/d/file/soft/sort01/sort016/2017-07-12/9e56a6da0e765ead099e80a0017698d2.jpg">《超级造化炉》全集</a>

这就是网页源码,看到规律直接正则即可获取

点击进小说详情页

详细页也一样

<a class="downButton" href='http://dzs.qisuu.com/txt/超级造化炉.txt' title="《超级造化炉》全集打包下载">Txt格式下载</a><div class="tabBox">兼容性最好的txt格式,支持所有设备(右键另存为下载)

思路清晰了,首先获取当前页小说详细页的地址和下一页地址,然后进入小说详细页获取下载地址并储存下来并反复循环。

爬虫程序有三个类,Mainwindow QT界面,http (封装get请求获取网页源码)

class http:public QObject
{Q_OBJECT
public:QByteArray get(const QString &strUrl);QByteArray post(const QString &strUrl, QByteArray data);
};
#include "http.h"
#include <QEventLoop>
#pragma execution_character_set("utf-8")QByteArray http::get(const QString &strUrl)
{const QUrl url = QUrl::fromUserInput(strUrl);QNetworkAccessManager m_qnam;QNetworkRequest qnr(url);QNetworkReply* reply = m_qnam.get(qnr); //m_qnam是QNetworkAccessManager对象QEventLoop eventLoop;connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);eventLoop.exec(QEventLoop::ExcludeUserInputEvents);QByteArray replyData = reply->readAll();int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();QVariant redirectAttr = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);if (reply->error()|| 300 == statusCode //状态码300 Multiple Choices,既不是错误也不算重定向,应该是qt bug|| !redirectAttr.isNull()){QString errString = reply->error() ? reply->errorString() : QString("发生重定向(%1),不允许此情况").arg(statusCode);qDebug()<<QString("发送get请求时出现错误:\n网址:%1\n错误信息:%2").arg(reply->request().url().toDisplayString(), errString);replyData.clear();}reply->deleteLater();reply = nullptr;//   qDebug()<<replyData.size();//  qDebug()<<replyData;return replyData;
}QByteArray http::post(const QString &strUrl, QByteArray data)
{const QUrl url = QUrl::fromUserInput(strUrl);
QByteArray replyData;QNetworkAccessManager m_qnam;QNetworkRequest qnr(url);qnr.setRawHeader("content-type","application/x-www-form-urlencoded");QNetworkReply* reply = m_qnam.post(qnr,data); //m_qnam是QNetworkAccessManager对象QEventLoop eventLoop;connect(reply, &QNetworkReply::finished, &eventLoop, &QEventLoop::quit);eventLoop.exec(QEventLoop::ExcludeUserInputEvents);QVariant statusCodeV =reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);QVariant redirectionTargetUrl =reply->attribute(QNetworkRequest::RedirectionTargetAttribute);if (reply->error() == QNetworkReply::NoError){replyData = reply->readAll();  // bytes//QString string(bytes); // stringQString string = QString::fromUtf8(replyData);qDebug()<<string.size();string=string.mid(0,5000);qDebug()<<string;}else{qDebug()<<reply->errorString();}reply->deleteLater();qDebug()<<replyData.size();qDebug()<<replyData;QJsonParseError json_error;QJsonDocument parse_doucment = QJsonDocument::fromJson(replyData, &json_error);if(json_error.error == QJsonParseError::NoError){if(parse_doucment.isObject()){QJsonObject obj = parse_doucment.object();if(obj.contains("info")){QJsonValue name_value = obj.take("info");if(name_value.isString()){QString ID = name_value.toString();qDebug()<<ID;//   processs_data.append(ID);}else{qDebug()<<"777";}}else{qDebug()<<"444";}}else{qDebug()<<"333";}}else{qDebug()<<"00";}return replyData;
}regular (正则表达式)#include "regular.h"regular::regular()
{}QStringList regular::search(QString regulardata,QString data)
{QStringList searchdata;QRegularExpression regularExpression(regulardata);int index = 0;QRegularExpressionMatch match;do {match = regularExpression.match(data, index);if(match.hasMatch()) {index = match.capturedEnd();searchdata.append(match.captured(0));//         qDebug()<<"("<<match.capturedStart()<<","<<index<<") "<<match.captured(0);} else {break;}} while(index < data.length());// qDebug()<<searchdata;return searchdata;
}QString regular::searchnextpage(QString data)
{QString i;QStringList linshi;i=QString("上一页(.*)下一页");linshi=search(i,data);if(linshi.size()>0){i=QString("a href='(.*)>下一页");linshi=search(i,linshi[0]);if(linshi.size()>0){linshi[0]=linshi[0].replace("a href='","");linshi[0]=linshi[0].replace("'>下一页","");//   qDebug()<<linshi[0];return linshi[0];}else{qDebug()<<"没有找到上下页";return "";}}else{qDebug()<<"没有找到上下页";return "";}
}QStringList regular::searchnovelurl(QString data)
{QString i=QString("<a href=(.*)<img src=");QStringList linshi;linshi=search(i,data);for(int a=0;a<linshi.size();a++){if(linshi[a].indexOf("html")==-1){//       qDebug()<<linshi[a]<<"移除";linshi.removeOne(linshi[a]);}}for(int a=0;a<linshi.length();a++){linshi[a].replace("<a href=\"","");linshi[a].replace("\"><img src=","");//   qDebug()<<linshi[a];}return linshi;
}QStringList regular::searchnoveldata(QString data)
{//查找小说下载地址QString novelname,novelauthor,noveltime,noveldownurl;QString regulardata="<div class=\"detail_right\">\r\n(.*)</h1>\r\n";QStringList searchdata=search(regulardata,data);QStringList test,test1;if(searchdata.size()>0){regulardata="<h1>(.*)</h1>";searchdata=search(regulardata,searchdata[0]);if(searchdata.size()>0){searchdata[0].replace("<h1>","");searchdata[0].replace("</h1>","");novelname=searchdata[0];                      //获取到小说名称}}else{qDebug()<<"查找小说名称时发生错误";}regulardata="书籍作者(.*)<";searchdata=search(regulardata,data);if(searchdata.size()>0){///有两种可能,1作者没有其他作品 2作者有其他作品可以直接点击链接搜索if(searchdata[0].indexOf("target")==-1)           //小说作者没其他作品{searchdata[0].replace("书籍作者:","");searchdata[0].replace("<","");novelauthor=searchdata[0];                         //获取到小说作者名}else{regulardata="blank(.*)</a>";searchdata=search(regulardata,searchdata[0]);if(searchdata.size()>0){searchdata[0].replace("blank\">","");searchdata[0].replace("</a>","");novelauthor=searchdata[0];                      //获取到小说名称}}}else{qDebug()<<"查找小说作者失败";}regulardata="发布日期(.*)<";searchdata=search(regulardata,data);if(searchdata.size()>0){searchdata[0].replace("发布日期:","");searchdata[0].replace("<","");noveltime=searchdata[0];                          //获取小说发布时间}else{qDebug()<<"查找小说时间失败";}regulardata="href=(.*)Txt格式下载";searchdata=search(regulardata,data);if(searchdata.size()>0){regulardata="href=(.*)txt";test.append(searchdata);searchdata=search(regulardata,searchdata[0]);if(searchdata.size()>0){searchdata[0].replace("href='","");searchdata[0].replace("<","");noveldownurl=searchdata[0];}else{qDebug()<<"查找小说下载地址失败2";qDebug()<<data;qDebug()<<test;noveldownurl="出错";}}else{qDebug()<<"查找小说下载地址失败1";qDebug()<<data.mid(10000,30000);novelname="出错";}
QStringList senddata;
//qDebug()<<novelname;
senddata.append(novelname);
senddata.append(novelauthor);
senddata.append(noveltime);
senddata.append(noveldownurl);return senddata;
}
MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
{ui->setupUi(this);int yeshu=1,xiaoshuoshu=1;QFile file("C:/Users/10515/Desktop/novel.txt");if(!file.open(QIODevice::ReadWrite | QIODevice::Text)) {qDebug()<<"Can't open the file!"<<endl;}QTextStream stream(&file);stream.seek(file.size());//将当前读取文件指针移动到文件末尾QList<QStringList>   novelinfo;QString weburl="";QString starturl="";
for(int h=0;;h++){QString data(web.get(starturl));//  qDebug()<<data.mid(0,30000);QStringList novelurl=zhengze.searchnovelurl(data);novel.append(novelurl);// qDebug()<<novelurl;QString     nextpage=zhengze.searchnextpage(data);//qDebug()<<nextpage;if(nextpage.size()>0)page.append(nextpage);for(int b=0;b<novel.size();b++){QString data1(web.get(weburl+novel[b]));QStringList result=zhengze.searchnoveldata(data1);novelinfo.append(result);stream <<result.join("    ")<<"\n";qDebug()<<xiaoshuoshu++<<"本"<<result.join("    ");}novel.clear();if(nextpage.size()==0)break;starturl=weburl+nextpage;qDebug()<<yeshu++<<"页";
}
qDebug()<<novel.size();
qDebug()<<page<<page.size();
qDebug()<<novelinfo;
file.close();
}

将小说地址都弄到一个txt文本内,然后写了一个专门的下载器下载

利用QT编写一个简单爬虫程序相关推荐

  1. 带你快速了解爬虫的原理及过程,并编写一个简单爬虫程序

    目录 前言 你应该知道什么是爬虫? 一.Scrapy的基本执行过程 二.Scrapy的实现 2.1Scrapy框架安装 2.2创建项目 (1)爬虫框架组件介绍 (2)控制台运行创建框架命令(spide ...

  2. 编写一个简单Java程序,计算银行年存款的本息

    编写一个简单Java程序,计算银行年存款的本息 要求:程序运行后要求用户输入存款本金.年利率和存款年限,最后程序计算并输出相应年限后存款的金额.相应的计算公式为:存款总额=本金 * (1 + 利率)存 ...

  3. 利用C#编写一个水准测量近似平差程序

    一.代码界面展示 整个界面主要就是就整个界面而言,其实主要使用到的控件就是Menu,tabControl,dataGridView,richtextbox. 二.代码运算结果展示 1.导入数据 这里就 ...

  4. java入门篇(一)如何编写一个简单的程序

    最近准备花费很长一段时间写一些关于Java的从入门到进阶再到项目开发的教程,希望对初学Java的朋友们有所帮助,更快的融入Java的学习之中. 主要内容包括JavaSE.JavaEE的基础知识以及如何 ...

  5. 【啃书C++Primer5】-编写一个简单C++程序

    每个C++程序都包含一个或多个函数(function),其中一个必须命名为main.操作系统通过调用main来运行C++程序.下面是一个非常简单的main函数,它什么也不干,只是返回给操作系统一个值: ...

  6. python编写一个简单的程序验证码_Python实现一个简单的验证码程序

    老师讲完random函数,自己写的,虽然和老师示例的不那么美观,智能,但是也自己想出来的,所以记录一下,代码就需要自己不断的自己练习,实战,才能提高啊!不然就像我们这些大部分靠自学的人,何时能学会.还 ...

  7. 用C语言编写一个“简单”的程序答题系统

    上个星期我们老师给我们布置一道他认为很简单的题,其实就想考考我们,要我们写一个简单的答题系统.开始一看只有一道题我直呼:"仰天大笑出门去,我辈岂是蓬蒿人" 以为老师放我一马,结果点 ...

  8. php编写一个简单计算器程序,PHP做一个简单的计算器

    本文为大家讲解通过分支循环知识及PHP的表单处理一个简单的计算器 首先看下效果 通过网页显示计算器样式 在网页样式中可以看出,有两个输入框Num1.Num2和一个下拉框Type 还有一个提交按钮 在输 ...

  9. 小程序一:利用Python编写一个简单的图书管理系统

    完成项目的流程: 想要完成某个项目基本都是按这个流程进行编写 想要实现的功能 代码的实现 class Book:def __init__(self,name,author,recommendation ...

最新文章

  1. 分享Kali Linux 2016.2第50周虚拟机
  2. 6、图书类别修改删除功能
  3. 调用者保存寄存器和非调用者保存寄存器
  4. Java基础教程【第一章:Java概述】
  5. 全国城市行政区划码Json格式
  6. java 解析ttf字体文件_stb_truetype解析ttf字体并将其保存到图片中
  7. 宋体小二对应html中css,CSS字体中英文姓名对照表:如宋体对应SimSun
  8. 【超图+CESIUM】【基础API使用示例】47、超图|CESIUM - 平行光源设置
  9. 数据分析之利用EXCEL做数据分析
  10. Angular-路由设置
  11. 联想thinkpad待机怎么唤醒_联想电脑睡眠无法唤醒_联想电脑睡眠怎么唤醒
  12. [VOT10](2022CVPR)TCTrack: Temporal Contexts for Aerial Tracking
  13. 收集的一些google搜索引擎技巧
  14. sqlmap tamper mysql_Sqlmap Tamper大全(1)
  15. 电机与运动控制笔记整理(三)——异步电机概述
  16. 改Android app字体,Android 开发之修改 app 的字体大小
  17. 还在买什么会员?你最需要的IDM下载利器来了~
  18. 命名管道的数据通信代码
  19. 服务器创建虚拟环境跑代码
  20. openlayers5之ol.proj坐标转换

热门文章

  1. 怎么开qq远程连接服务器,关于QQ远程控制的问题设置了远程控制服务端后怎样运行到QQ对象中 爱问知识人...
  2. connectionstrings(connectionstrings)
  3. vue 在style标签中引入js变量控制样式
  4. 移动端H5网页开发常见问题汇总
  5. python psutil模块查找进程_python模块 - psutil
  6. CERT-JAVA Atomicity、 Visibility and Atomicity
  7. 智慧工厂之化工厂人员定位,化工厂区域视频联动管理-新导智能
  8. 计算机编程form什么意思,FORM
  9. Nokia N95 8G刷机
  10. google android plc,Android Studio 4.0发布 为Android 11做好准备