前言:因为学习需要,有时候需要查看WebMagic的官方的文档,但是官方的文档是搭建在GitBook上面的,它的服务器在国外,有时候访问不是太顺畅,因此萌生了把GitBook上面的网页保存到本地的想法,这样就可以离线查看了文档了,不用受制于网络的问题。



思路

思路:我大致查看了gitbook上面的网页结构,左右是目录,右边是内容,这种方式阅读确实是挺方便的。然后抓取的思路也就是首先一次性把左右所有目录的url加入调度队列,然后依次下载每一页的html,然后将html转成markdown文本的形式。

文档的结构
文档页面的结构

文档的目录
这里我使用css选择器来处理,正则和xpath我都不太熟悉,选择器相对来说简单一些。
通过调试窗口可以看出所有目录的url在class="book-summary"元素中。
在这里插入图片描述



文档的内容部分
通过调试窗口可以发现文档的主要内容都在clsss="book-body"元素中。
在这里插入图片描述

代码

BookPageProcessor类

package dragon_spider;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;

import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.processor.PageProcessor;

public class BookPageProcessor implements PageProcessor {
	
	private static int count = 1;
	
	private static boolean flag = true;
	
	private Site site = Site.me()
							.setRetryTimes(3)
							.setSleepTime(100);
	
	public void process(Page page) {
		if (flag) { // 获取所有的 目录url
			flag = false;  // 目录url只需要获取一次即可。
			List<String> liList = page.getHtml()
					.$("div.book-summary > nav > ul > li")
					.links()
					.all();		
			liList.remove(liList.size()-1);
			page.addTargetRequests(liList);
		} 
		// 下载目录url对应的html
		String htmlPart = page.getHtml().$("#book-search-results > div.search-noresults > section").toString();  // 获取与内容相关的部分
		System.out.println("抓取完成 " + (count++) +" 页!");
		page.putField("html", htmlPart);
	}
	
	public Site getSite() {
		return site;
	}
	
	public static void main(String[] args) {
		Path filePath = Paths.get("C:", "Users", "Alfred", "Desktop", "code", "data", "webmagic_doc.html");
		try {
			// 创建保存html的文件,启动程序前需要检查文件是否存在,如果存在程序无法启动。
			Files.createFile(filePath);
			// 开始爬取html文件
			Spider.create(new BookPageProcessor())
			.addUrl("http://webmagic.io/docs/zh/")
			.addPipeline(new HtmlFilePipeLine(filePath))
			.thread(1)
			.start();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

注意:这段代码,需要手动去掉最后一个url。

List<String> liList = page.getHtml()
					.$("div.book-summary > nav > ul > li")
					.links()
					.all();		
liList.remove(liList.size()-1);

通过css选择器会匹配到最后一个gitbook的官方链接,但是我是不需要它的。如下是上面代码执行后,List中的所有元素,可见总共有38条url,去掉最后一个元素,总共需要爬取的是37个页面。

在这里插入图片描述



HtmlFilePipeLine类
这里我自己实现了一个自定义的PipeLine类,其实是可以使用官方的FilePipeLine类的,但是一开始我是考虑每一个页面单独存放的,但是那样过于麻烦了。一个37个html文件,然后转换成markdown文件后,就是37个markdown文件。经过我对markdown文件的简单了解,我需要的是目录,所以所有的文件内容应该是在一起的,所以就修改了一下。

package dragon_spider;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;

import us.codecraft.webmagic.ResultItems;
import us.codecraft.webmagic.Task;
import us.codecraft.webmagic.pipeline.Pipeline;

public class HtmlFilePipeLine implements Pipeline {
	
	private Path filePath;
	
	public HtmlFilePipeLine(Path filePath) {
		this.filePath = filePath;
	}
	
	public void process(ResultItems resultItems, Task task) {
		resultItems.getAll().forEach((k, v) -> {
			try {
				Files.write(filePath, v.toString().getBytes(StandardCharsets.UTF_8), StandardOpenOption.APPEND);
			} catch (IOException e) {
				e.printStackTrace();
			}
		});
	}

}

运行结果

控制台输出
在这里插入图片描述

生成的html文件
在这里插入图片描述

html转markdwon

本来是打算寻找一个Java库来解决这个问题的,但是发现基本上都是markdown转html这种库,最后发现一个Java库,但是它是一个Gradle工程。由于我对于Gradle的概念,只有那个大象图标,所以我就放弃了。转而寻求其它方法,最后还是万能的python起了作用。python有一个库——html2text,可以帮助我实现这个功能。所以这个转换就使用python来实现了。不过我的水平仅限于了解基本语法了,读写文件的方法也是当场百度的,好在我的功能只是读取文件,转换,写入文件三个步骤,还是不难解决的。 不过这也说明,技多不压身呀,还是得多学习才行!

html2md.py

# -*- coding: utf-8 -*-
import html2text
import os

h2md = html2text.HTML2Text()
h2md.ignore_links=False

dir_path = r"C:\Users\Alfred\Desktop\code\data"
filenames = os.listdir(dir_path)
for filename in filenames:
    filepath = os.path.join(dir_path, filename)
    new_file_path = os.path.join(dir_path, filename+".md")
    file = open(filepath, "r", encoding="UTF-8")
    html_content = file.read()
    md_content = h2md.handle(html_content)
    file = open(new_file_path, "w", encoding="UTF-8")
    file.write(md_content)

print("程序执行完成!")

运行结果
在这里插入图片描述

使用Typora打开,按如下方式选择 视图->大纲 预览一下:
在这里插入图片描述

预览效果

在这里插入图片描述

在这里插入图片描述
说明:效果还是很不错的,只是目录有些许差异,因为这里的目录是按照标题来分的,可能和网页上面是有区别的,不过对于阅读应该是没有什么影响了。

注意:这里我提一下,最后的效果和官方文档其实很像,主要原因是官方文档也是采用的markdown的形式展示内容的,所以我把html标签再转markdown,也就和官方文档很像,但是对于其它的网页文件,不一定有这个效果了。

所有的显示内容都在section标签中,而它的类选择器中有一个markdown-section
在这里插入图片描述

总结

这个例子的有趣之处在于,我是使用了WebMagic来爬取WebMagic了,我爬我自己。哈哈。因为好久没写了,上次入门学习的知识也都忘记了,我也是参考着官方文档的第一个示例程序来抓取官方文档的。而且,本地访问速度有时候确实太慢了,容易断开连接了。这样抓取下来,放在本地随时都可以看,希望可以帮助到有需要的人。

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐