果然我的正则表达式写错了

Q:为什么玩春物哏,你不是还没看吗?
A:因为我整这玩意就是为了下载春物啊……

没错,为了在 wenku8 上下载全篇小说,这个人用 C++ 写了个小脚本。

甚至这人不会多线程,下载只会用curl

然后下载速度巨慢,爬爬爬。

我们姑且不提某个已经完善然而只能下epub的下载器

wenku8 除了无版权小说的插图下载以外都被人研究透彻了。现在下载无版权小说插图还是只能跑几十万次请求。

已解决问题

正则表达式从不会到不会

有人说用正则表达式徒增负担,但没正则我更不会写。

于是 30min 修炼正则表达式基础,玩 RegExr(顺带一提这网站在今天下午证书过期了,真是够巧的)。

curl从不会到略懂

啊这个东西好像还真是学学就行。

大概就主要看了这一篇

在C++中实现编码互转

至今不会,所以脚本中完全没有关于这个的。

code

过程经历太多,只留下这份代码来表示我的付出终于有了些回报。

编译后运行,输入文章 id 即可观察到它慢慢爬爬爬。

顺带一提由于上面说的原因不能下载无版权小说的插图。

命名格式不规范警告.webp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
//author: Okazaki Yumemi
//v0.0.1
//c++11
#include<bits/stdc++.h>
using namespace std;

inline string IntToString(const int &x){
if(x < 0) return "-" + IntToString(-x);
if(x < 10) return string(1, char(x ^ 48));
return IntToString(x / 10) + char((x % 10) ^ 48);
}
inline int StringToInt(const string &x){
const int &len = x.length();
assert(isdigit((char)x[len - 1]));
if(len == 1){
return (char)x[0] ^ 48;
}
return StringToInt(x.substr(0, len - 1)) * 10 + ((char)x[len - 1] ^ 48);
}

const regex ChapterPattern("href=\"\\d{1,9}.htm\""), VolumePattern("colspan=\"4\""), IllustPattern("src=\"http://picture.wenku8.com/pictures/\\d{1,9}/\\d{1,9}/\\d{1,9}/\\d{1,9}.(jpg|png)\""), IllustNamePattern("\\d{1,9}.(jpg|png)");
typedef string::const_iterator iter;

ifstream Origin;
string Contents;
smatch ChapterResult, VolumeResult, VolumeNextResult;
string BasicUrl, ArticleName;

void IllustDownload(const string &VolumeName){
ifstream IllustOrigin(".\\illust.htm");
string IllustContents((istreambuf_iterator<char>(IllustOrigin)), istreambuf_iterator<char>());
smatch IllustResult, FileNameResult;
iter IllustBegin = IllustContents.begin(), IllustEnd = IllustContents.end();

while(regex_search(IllustBegin, IllustEnd, IllustResult, IllustPattern)){
string IllustGet(IllustResult[0], 5, IllustResult[0].length() - 6);
regex_search(iter(IllustGet.begin()), iter(IllustGet.end()), FileNameResult, IllustNamePattern);
string DownloadIllust = "curl -o .\\" + VolumeName + "\\" + string(FileNameResult[0]) + " " + IllustGet;
// cout << DownloadIllust << "\n";
system(DownloadIllust.c_str());
// puts(DownloadIllust.c_str());
IllustBegin = IllustResult[0].second;
}
}

void ArticleInit(){
int ArticleId;
puts("Article id:");
// scanf("%d", &ArticleId);
cin >> ArticleId;
ArticleName = IntToString(ArticleId);

BasicUrl = "https://www.wenku8.net/novel/" + IntToString(ArticleId / 1000) + "/" + ArticleName + "/";
// string ArticleDescriptionDownload = "curl -v " + BasicUrl + "index.htm > origin.htm";
string ArticleDescriptionDownload = "curl " + BasicUrl + "index.htm > origin.htm";
// system("rm origin.htm");
system(ArticleDescriptionDownload.c_str());
}
void ArticleDownload(){
Origin = ifstream(".\\origin.htm");
Contents = string((istreambuf_iterator<char>(Origin)), istreambuf_iterator<char>());


int VolumeNow = 0;
iter VolumeIterBegin = Contents.begin(), VolumeIterEnd = Contents.end();
iter ChapterIterBegin, ChapterIterEnd;

VolumeIterBegin = regex_search(VolumeIterBegin, VolumeIterEnd, VolumeNextResult, VolumePattern) ? VolumeNextResult[0].second : VolumeIterEnd;
while(VolumeIterBegin < VolumeIterEnd){
++VolumeNow;
string VolumeName = IntToString(VolumeNow);
// printf("Vol: %d\n", VolumeNow);

string MkVolumeDir = "mkdir " + VolumeName;
system(MkVolumeDir.c_str());

VolumeResult = VolumeNextResult;
bool LastVolume = !regex_search(VolumeIterBegin, VolumeIterEnd, VolumeNextResult, VolumePattern);
ChapterIterBegin = VolumeIterBegin;
VolumeIterBegin = ChapterIterEnd = LastVolume ? VolumeIterEnd : VolumeNextResult[0].second;

string ChapterGet, UrlName;

while(regex_search(ChapterIterBegin, ChapterIterEnd, ChapterResult, ChapterPattern)){
ChapterGet = string(ChapterResult[0], 6, ChapterResult[0].length() - 11);
UrlName = IntToString(StringToInt(ChapterGet) - 1);

// cout << UrlName << "\n";
string DownloadUTF8 = "curl -o \".\\" + VolumeName + "\\" + ChapterGet + " utf8.txt\" \"http://dl.wenku8.com/packtxt.php?aid=" + ArticleName + "&vid=" + UrlName + "&charset=utf8\"";
string DownloadGBK = "curl -o \".\\" + VolumeName + "\\" + ChapterGet + " gbk.txt\" \"http://dl.wenku8.com/packtxt.php?aid=" + ArticleName + "&vid=" + UrlName + "&charset=gbk\"";
string DownloadBIG5 = "curl -o \".\\" + VolumeName + "\\" + ChapterGet + " big5.txt\" \"http://dl.wenku8.com/packtxt.php?aid=" + ArticleName + "&vid=" + UrlName + "&charset=big5\"";

system(DownloadUTF8.c_str());
system(DownloadGBK.c_str());
system(DownloadBIG5.c_str());
// puts(DownloadUTF8.c_str());
// puts(DownloadGBK.c_str());
// puts(DownloadBIG5.c_str());

ChapterIterBegin = ChapterResult[0].second;
}

// system("rm illust.htm");
// string DownloadIllust = "curl -v " + BasicUrl + ChapterGet + ".htm > illust.htm";
string DownloadIllust = "curl " + BasicUrl + ChapterGet + ".htm > illust.htm";
system(DownloadIllust.c_str());

IllustDownload(VolumeName);
// cout << DownloadIllust << "\n";
}
}

int main(){
ArticleInit();
ArticleDownload();
return 0;
}

未解决

多线程下载

不会,咕了。

部分文章的vid非章节号减去1

正解也许是章节号 -1,0,+1 都有可能。

这个下次来修。

断点续传

偶尔来个网不稳就会出现 Time Out,被迫全部重下。

所以啥时候写个断点续传啊(