爬小說

問題:

看小說有很多廣告,使用迅雷下載,如果文件名稱沒有規律的話,下載效率很低,因爲猜不到文件名規律。於是就想每一章都有下一章,因此可以根據"下一章" 找到 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 格式需要轉碼,然後再進行查找.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章