問題:
看小說有很多廣告,使用迅雷下載,如果文件名稱沒有規律的話,下載效率很低,因爲猜不到文件名規律。於是就想每一章都有下一章,因此可以根據"下一章" 找到 href 然後下載下一章,如果"下一章"已經下載則說明循環了,要停止。下載完以後,需要生成新的小說文件,可以根據小說的開始位置的特點和結束位置特點進行獲取文件內容,並且生成目錄。這樣一本小說就加工出來了。
下面是爬小說的部分,使用了 curl 下載 vs2019 c++ 實現。
#include <tchar.h>
#include <Windows.h>
#include <stdio.h>
#include <string>
#include <Shlwapi.h>
#include <processthreadsapi.h>
#include <iostream>
#include <vector>
#include <atlconv.h>
using namespace std;
#pragma comment(lib,"shlwapi.lib")
vector<wstring> g_vecFiles;
//獲得路徑的文件名
static wstring getfilename(wstring& path)
{
wstring result;
wchar_t* p = (wchar_t*)path.data();
wchar_t* pos = NULL;
for (;;)
{
wchar_t c = *p;
if (c == L'/')
{
pos = p + 1;
}
if (c == 0)
{
result = *(pos) ? pos : L"";
break;
}
p++;
}
return result;
}
//下載url指向的文件
static wstring ObtainHtmlFile(wstring& url)
{
wchar_t cmdline[512];
wstring filename = getfilename(url);
wsprintf(cmdline, L"curl -G -o d:\\temp\\%s %s", filename.c_str(), url.c_str());
STARTUPINFO info = { sizeof(info) };
PROCESS_INFORMATION pi;
BOOL b = CreateProcess(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &info, &pi);
if (b)
{
WaitForSingleObject(pi.hThread, INFINITE);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
return wstring(L"d:\\temp\\") + filename;
}
return L"";
}
//獲得文件內容
static string ObtainFileContent(wstring& file)
{
string result;
FILE* fp = _wfopen(file.c_str(), L"rb");
if (fp)
{
fseek(fp, 0, SEEK_END);
int len = ftell(fp);
fseek(fp, 0, SEEK_SET);
result.resize(len, 0);
fread((char*)result.data(), 1, len, fp);
fclose(fp);
}
return result;
}
//獲得下一章
static wstring ObtainNextChapter(string& content)
{
wstring result;
const char* index_str = ">下一章</a>";
int index = content.find(index_str);
if (index != -1)
{
const char* next_find_str = "href=\"";
index = content.rfind(next_find_str, index);
index += strlen(next_find_str);
int index1 = content.find("\"", index);
string url;
url.insert(url.begin(), content.begin() + index, content.begin() + index1);
USES_CONVERSION;
result = A2W(url.c_str());
}
return result;
}
int _tmain(int argc, TCHAR* argv)
{
wstring url;
url = L"https://www.biqushu.com/book_74884/26144503.html";
while (1) {
//查找是否結束
for (wstring x : g_vecFiles)
{
if (url == x)
{
//成環了
goto over;
}
else if (url.empty())
{
goto over;
}
}
g_vecFiles.push_back(url);
//獲得文件
int times = 5;
while (times > 0)
{
wstring str = ObtainHtmlFile(url);
if (PathFileExists(str.c_str()))
{
//解析文件獲得文件的下一章
string content = ObtainFileContent(str);
url = ObtainNextChapter(content);
break;
}
else
{
times--;
continue;
}
}
}
over:
for (auto x : g_vecFiles)
{
USES_CONVERSION;
cout << W2A(x.c_str()) << endl;
}
return 0;
}
文件生成到了 d:\temp 目錄下。程序很短,也很簡單,不過多說明了。HTML 是 GBK ,因此使用 單字符解析,如果是UTF-8 格式需要轉碼,然後再進行查找.