精华内容
下载资源
问答
  • WebMagic

    2019-11-27 17:48:10
    WebMagic项目代码分为核心和扩展两部分。核心部分(webmagic-core)是一个精简的、模块化的爬虫实现,而扩展部分则包括一些便利的、实用性的功能。扩展部分 (webmagic-extension)提供一些便捷的功能,例如注解模式编写...

    架构解析

    WebMagic项目代码分为核心和扩展两部分。核心部分(webmagic-core)是一个精简的、模块化的爬虫实现,而扩展部分则包括一些便利的、实用性的功能。扩展部分 (webmagic-extension)提供一些便捷的功能,例如注解模式编写爬虫等。同时内置了一些常用的组件,便于爬虫开发。

    WebMagic的设计目标是尽量的模块化,并体现爬虫的功能特点。这部分提供非常简单、灵活的API,在基本不改变开发模式的情况下,编写一个爬虫。 ​

    WebMagic的结构分为Downloader、PageProcessor、Scheduler、Pipeline四大组件,并由Spider将它们彼此组织起来。这四大组件对应爬虫生命周期中的下载、处理、管理和持久化等功能。而Spider则将这几个组件组织起来,让它们可以互相交互,流程化的执行,可以认为Spider是一个大的容器,它也是WebMagic逻辑的核心。
    在这里插入图片描述
    四大组件

    • Downloader

    Downloader负责从互联网上下载页面,以便后续处理。WebMagic默认使用了 ApacheHttpClient作为下载工具。

    • PageProcessor

    PageProcessor负责解析页面,抽取有用信息,以及发现新的链接。WebMagic使用Jsoup 作为HTML解析工具,并基于其开发了解析XPath的工具Xsoup。在这四个组件中,PageProcessor对于每个站点每个页面都不一样,是需要使用者定制的部分。

    • Scheduler

    Scheduler负责管理待抓取的URL,以及一些去重的工作。WebMagic默认提供了JDK的内存队列来管理URL,并用集合来进行去重。也支持使用Redis进行分布式管理。

    • Pipeline

    Pipeline负责抽取结果的处理,包括计算、持久化到文件、数据库等。WebMagic默认提供 了“输出到控制台”和“保存到文件”两种结果处理方案。

    PageProcessor

    需求:编写爬虫程序,爬取csdn中博客–Java的内容

    爬取页面全部内容

    https://blog.csdn.net/nav/java
    (1)创建工程,引入依赖

    <dependency>
    	<groupId>us.codecraft</groupId>
    	<artifactId>webmagic-core</artifactId>
    	<version>0.7.3</version>
    </dependency>
    <dependency>
    	<groupId>us.codecraft</groupId>
    	<artifactId>webmagic-extension</artifactId>
    	<version>0.7.3</version>
    </dependency>
    

    (2)编写类实现网页内容的爬取

    public class ProcessDemo1 implements PageProcessor {
    
    	public void process(Page page) {
    		System.out.println(page.getHtml().toString()); // 抓取全部内容
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo1()).addUrl("https://blog.csdn.net/").run();
    	}
    
    }
    

    Spider是爬虫启动的入口。在启动爬虫之前,我们需要使用一个PageProcessor创建 一个Spider对象,然后使用run()进行启动。

    方法说明示例
    create(PageProcessor)创建SpiderSpider.create(new GithubRepoProcessor())
    addUrl(String…)添加初始的URLspider.addUrl(“http://webmagic.io/docs/”)
    thread(n)开启n个线程spider.thread(5)
    run()启动,会阻塞当前线程执行spider.run()
    start()/runAsync()异步启动,当前线程继续执行spider.start()
    stop()停止爬虫spider.stop()
    addPipeline(Pipeline)添加一个Pipeline,一个Spider可以有多个Pipelinespider.addPipeline(new ConsolePipeline())
    setScheduler(Scheduler)设置Scheduler,一个Spider只能有个一个Schedulerspider.setScheduler(new RedisScheduler())
    setDownloader(Downloader)设置Downloader, 一个Spider只能有个一个Downloaderspider.setDownloader( new SeleniumDownloader())
    get(String)同步调用,并直接取得结果ResultItems result = spider.get(“http://webmagic.io/docs/”)
    getAll(String…)同步调用,并直接取得一堆结果List results = spider.getAll(“http://webmagic.io/docs/”, “http://webmagic.io/xxx”)

    同时Spider的其他组件(Downloader、Scheduler、Pipeline)都可以通过set方法来 进行设置。

    Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者 其他文本格式的内容。Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽 取、结果保存等。

    ​Site用于定义站点本身的一些配置信息,例如编码、HTTP头、超时时间、重试策略等、代理等,都可以通过设置Site对象来进行配置

    方法说明示例
    setCharset(String)设置编码site.setCharset(“utf-8”)
    setUserAgent(String)设置 UserAgentsite.setUserAgent(“Spider”)
    setTimeOut(int)设置超时时间,单位是毫秒site.setTimeOut(3000)
    setRetryTimes(int)设置重试次数site.setRetryTimes(3)
    setCycleRetryTimes(int)设置循环重试次数site.setCycleRetryTimes(3)
    addCookie(String,String)添加一条cookiesite.addCookie(“dotcomt_user”,“code4craft”)
    setDomain(String)设置域名,需设置域名后,addCookie才可生效site.setDomain(“github.com”)
    addHeader(String,String)添加一条 addHeadersite.addHeader(“Referer”,“https://github.com”)
    setHttpProxy(HttpHost)设置Http代理site.setHttpProxy(new HttpHost(“127.0.0.1”,8080))

    爬取指定内容(XPath)

    ​ 如果我们想爬取网页中部分的内容,需要指定xpath。

    ​XPath,即为XML路径语言(XMLPathLanguage),它是一种用来确定XML文档中某 部分位置的语言。XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。这些路径 表达式和我们在常规的电脑文件系统中看到的表达式非常相似。语法详见XPath语法

    通过指定xpath来抓取网页的部分内容

    public class ProcessDemo2 implements PageProcessor {
    
    	public void process(Page page) {
    		System.out.println(page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[5]/a").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo2()).addUrl("https://blog.csdn.net/").run();
    	}
    
    }
    

    以上代码的含义:id为nav的节点下的div节点下的div节点下的ul下的第5个li节点下的a节点
    看一下输出结果

    <a href="/nav/java">Java</a>
    

    添加目标地址

    我们可以通过添加目标地址,从种子页面爬取到更多的页面

    public class ProcessDemo3 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(page.getHtml().links().all()); // 添加全部地址
    		System.out.println(page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[5]/a").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo3()).addUrl("https://blog.csdn.net/").run();
    	}
    
    }
    

    运行后发现好多地址都出现在控制台

    目标地址正则匹配

    需求:只提取播客的文章详细页内容,并提取标题

    public class ProcessDemo4 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(
    				page.getHtml().links().regex("https://blog.csdn.net/weixin_45730091/article/details/[0-9]{9}").all());
    		page.putField("title",
    				page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div[1]/div/div[1]/h1/text()").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo4()).addUrl("https://blog.csdn.net/weixin_45730091").run();
    	}
    
    }
    

    Pipeline

    ConsolePipeline 控制台输出

    public class ProcessDemo5 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(
    				page.getHtml().links().regex("https://blog.csdn.net/weixin_45730091/article/details/[0-9]{9}").all());
    		page.putField("title",
    				page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div[1]/div/div[1]/h1/text()").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo5()).addUrl("https://blog.csdn.net/weixin_45730091")
    				.addPipeline(new ConsolePipeline())// 控制台输出
    				.run();
    	}
    
    }
    

    FilePipeline 文件保存

    public class ProcessDemo6 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(
    				page.getHtml().links().regex("https://blog.csdn.net/weixin_45730091/article/details/[0-9]{9}").all());
    		page.putField("title",
    				page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div[1]/div/div[1]/h1/text()").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo6()).addUrl("https://blog.csdn.net/weixin_45730091")
    				.addPipeline(new ConsolePipeline())// 控制台输出
    				.addPipeline(new FilePipeline("e:/p"))// FilePipeline 文件保存
    				.run();
    	}
    
    }
    

    JsonFilePipeline

    以json方式保存

    public class ProcessDemo7 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(
    				page.getHtml().links().regex("https://blog.csdn.net/weixin_45730091/article/details/[0-9]{9}").all());
    		page.putField("title",
    				page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div[1]/div/div[1]/h1/text()").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo7()).addUrl("https://blog.csdn.net/weixin_45730091")
    				.addPipeline(new ConsolePipeline())// 控制台输出
    				.addPipeline(new FilePipeline("e:/p"))// FilePipeline 文件保存
    				.addPipeline(new JsonFilePipeline("e:/pjson"))// 以json方式保存
    				.run();
    	}
    
    }
    

    定制Pipeline

    如果以上Pipeline都不能满足你的需要,你可以定制Pipeline
    (1)创建类PipelineDemo实现接口Pipeline

    public class PipelineDemo implements Pipeline {
    
    	public void process(ResultItems resultItems, Task task) {
    		String title = resultItems.get("title");
    		System.out.println("我的定制的 title:" + title);
    	}
    
    }
    

    (2)修改main方法

    public class ProcessDemo8 implements PageProcessor {
    
    	public void process(Page page) {
    		// 添加目标地址
    		page.addTargetRequests(
    				page.getHtml().links().regex("https://blog.csdn.net/weixin_45730091/article/details/[0-9]{9}").all());
    		page.putField("title",
    				page.getHtml().xpath("//*[@id=\"mainBox\"]/main/div[1]/div[1]/div/div[1]/h1/text()").toString());
    	}
    
    	public Site getSite() {
    		// setRetryTimes 设置重试次数
    		// setSleepTime 设置时间间隔(毫秒) 默认5秒
    		return Site.me().setRetryTimes(3).setSleepTime(100);
    	}
    
    	public static void main(String[] args) {
    		Spider.create(new ProcessDemo8()).addUrl("https://blog.csdn.net/weixin_45730091")
    				.addPipeline(new ConsolePipeline())// 控制台输出
    				.addPipeline(new FilePipeline("e:/p"))// FilePipeline 文件保存
    				.addPipeline(new JsonFilePipeline("e:/pjson"))// 以json方式保存
    				.addPipeline(new PipelineDemo())// 定制Pipeline
    				.run();
    	}
    
    }
    

    Scheduler

    我们刚才完成的功能,每次运行可能会爬取重复的页面,这样做是没有任何意义的。

    Scheduler(URL管理) 基本的功能是实现对已经爬取的URL进行标示。可以实现URL的增 量去重。
    目前scheduler主要有三种实现方式:

    1. 内存队列 QueueScheduler
    2. 文件队列 FileCacheQueueScheduler
    3. Redis队列 RedisScheduler

    内存队列

    使用setScheduler来设置Scheduler

    public static void main(String[] args) {
    	Spider.create(new ProcessDemo9()).addUrl("https://blog.csdn.net/weixin_45730091")
    			.setScheduler(new QueueScheduler())// 内存队列
    			.run();
    }
    

    文件队列

    使用文件保存抓取URL,可以在关闭程序并下次启动时,从之前抓取到的URL继续抓取
    (1)创建文件夹E:\scheduler
    (2)修改代码

    public static void main(String[] args) {
    	Spider.create(new ProcessDemo10()).addUrl("https://blog.csdn.net/weixin_45730091")
    			.setScheduler(new FileCacheQueueScheduler("e:/mysch"))// 文件队列
    			.run();
    }
    

    运行后文件夹E:\scheduler会产生两个文件

    Redis队列

    使用Redis保存抓取队列,可进行多台机器同时合作抓取
    (1)运行redis服务端
    (2)修改代码

    public static void main(String[] args) {
    	Spider.create(new ProcessDemo11()).addUrl("https://blog.csdn.net/weixin_45730091")
    			.setScheduler(new RedisScheduler("127.0.0.1"))// Redis队列
    			.run();
    }
    
    展开全文
  • webmagic

    2018-01-19 14:20:02
    http://webmagic.io/http://webmagic.io/docs/zh/
    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,016
精华内容 1,606
关键字:

webmagic