1
2<html lang="en">
3
6<head>
7 <title>文章标题1title>
8head>
9<title>文章标题2title>
10<body>
11<div id="d1">div1div>
12<div class="c2">div2div>
13<div>div3div>
14<div class="c2">div4div>
15body>
16html>
可能有很多小伙伴不了解Xpath语法是什么,我就给大家稍微介绍下,想要了解更多可以百度或者后台联系我,XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。因此,对 XPath 的理解是很多高级 XML 应用的基础。下图是一些Xpath语法最有用的路径表达式;
插录来源:
https://www.w3school.com.cn/xpath/xpath_syntax.asp
大家可以在上面的地址学习Xpath语法解析,我看了下,里面的内容很详细,感兴趣的小伙伴就去了解下,
1需求:
21)获取title标签,在title前面添加两个斜杠即可
3 /html/head/title
4 //title
5
62)获取div标签,只能拿到第一个div,在div前面添加两个斜杠即可
7 /html/body/div
8 //div
9
103)获取第二个div在div之前添加双斜杠并在后面添加数组并设值
11 //div[2]
12
134)获取最后一个div,在div前面添加双斜杠,后面数组内设置last()方法
14 //div[last()]
15
165) 获取有属性的div,在div前面添加双斜杠,后面添加数组并设置@值
17 //div[@]
18
196)获取有id属性的div,在div前面添加双斜杠,后面添加数组并设置@id值
20 //div[@id]
21
227)获取id属性值为d1的div,在div前面添加双斜杠,后面添加数组并设置@id='d1'的值
23 //div[@id='d1']
24
258)获取head下所有标签,在head前面添加双斜杠,后面添加/*
26 //head/*
现在我们现在通过浏览器查看网页的信息,点击某个段落,右键检查,然后在右键,选择Copy里面的Comp XPath,如下图操作,并且将复制的Xpath内容粘贴到page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[4]/a").toString();里面,如下代码
1package com.mobaijun;
2
3import us.codecraft.webmagic.Page;
4import us.codecraft.webmagic.Site;
5import us.codecraft.webmagic.Spider;
6import us.codecraft.webmagic.processor.PageProcessor;
7
8/**
9 * @Author:Auser·杰
10 * @DATE:2019/10/28 19:57
11 */
12public class MyPageProcessor implements PageProcessor {
13 /**
14 * 解析网页内容
15 */
16 @Override
17 public void process(Page page) {
18 //爬取指定网页内容(xpath表达式)
19 // 把刚刚copy的Xpath内容复制到这里
20 String content = page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[3]/a").toString();
21 String content2 = page.getHtml().xpath("//*[@id=\"nav\"]/div/div/ul/li[4]/a").toString();
22 System.out.println(content);
23 System.out.println(content2);
24
25 }
26
27 /**
28 * 设置爬取参数
29 */
30 @Override
31 public Site getSite() {
32 return Site.me()
33 .setSleepTime(100)// 设置爬取间隔时间
34 .setTimeOut(3000)// 设置爬取超时时间
35 .setRetryTimes(3);// 设置重试次数
36
37 }
38
39 public static void main(String[] args) {
40 /**
41 * 入口
42 */
43 Spider
44 .create(new MyPageProcessor())
45 .addUrl("https://www.某N.net/")
46 .start();
47 }
48}
很多时候我们想要爬取的内容并不是一整个页面的内容,可能我们只需要爬取一两个url链接或者是别的什么,这个时候我们就可以使用正则表达式过滤那些非目标内容来获取我们想要的内容,详细操作看下方代码,
1package com.mobaijun.processer;
2
3import us.codecraft.webmagic.Page;
4import us.codecraft.webmagic.Site;
5import us.codecraft.webmagic.Spider;
6import us.codecraft.webmagic.processor.PageProcessor;
7
8/**
9 * 我们自己的处理器
10 */
11public class MyPageProcesser implements PageProcessor{
12 /**
13 * 处理,解析页面
14 */
15 @Override
16 public void process(Page page) {
17 //1、输出页面的内容
18 //System.out.println(page.getHtml().toString());
19
20 //2、通过xpath获取指定的内容
21 //System.out.println(page.getHtml().xpath("//*[@id=\"mainScreen\"]/div/div[1]/div/div[1]/div[1]/a[2]").toString());
22 //System.out.println(page.getHtml().xpath("//*[@id=\"mainScreen\"]/div/div[1]/div/div[1]/div[1]/a[2]/text()").toString());
23
24 //3、爬取指定的url
25 //3.1 所有url
26 //System.out.println(page.getHtml().links().all().toString());
27 //进入所有连接的页面
28 //page.addTargetRequests(page.getHtml().links().all());
29
30 //3.2 使用正则表达式解析具体url
31 //System.out.println(page.getHtml().regex("https://my.oschina.net/u/[0-9]{7}/blog/[0-9]{7}").all().toString());
32 page.addTargetRequests(page.getHtml().regex("https://my.oschina.net/u/[0-9]+/blog/[0-9]+").all());
33 }
34 /**
35 * 站点处理:超时的时间,重试次数等
36 */
37 @Override
38 public Site getSite() {
39 return Site.me()
40 .setSleepTime(300)//爬取完一次,休眠时间
41 .setTimeOut(3000)//设置超时时间
42 .setRetryTimes(3)//设置重试次数
43 ;
44 }
45
46 /**
47 * 运行
48 */
49 public static void main(String[] args) {
50
51 Spider
52 .create(new MyPageProcesser())// 创建
53 .addUrl("https://www.某n.net/blog") //加入页面链接
54 .start(); //开始爬取
55 ;
56
57 }
58}
结果:
一般我们爬取的内容是不会放在控制台打印输出的,而是存储在磁盘空间或者是数据库中,下面通过代码来演示;
1package com.mobaijun;
2
3import org.apache.commons.lang3.StringUtils;
4import us.codecraft.webmagic.Page;
5import us.codecraft.webmagic.Site;
6import us.codecraft.webmagic.Spider;
7import us.codecraft.webmagic.pipeline.ConsolePipeline;
8import us.codecraft.webmagic.pipeline.FilePipeline;
9import us.codecraft.webmagic.pipeline.JsonFilePipeline;
10import us.codecraft.webmagic.processor.PageProcessor;
11import us.codecraft.webmagic.scheduler.RedisPriorityScheduler;
12
13import java.util.List;
14
15/**
16 * @Author:Auser·杰
17 * @DATE:2019/10/28 19:57
18 */
19public class MyPageProcessor implements PageProcessor{
20
21 private Site site = Site.me()
22 .setRetryTimes(1) //重试
23 .setSleepTime(1000) //休眠时间
24 .setTimeOut(10000); //超时时间
25
26 /**
27 * 页面处理
28 */
29 @Override
30 public void process(Page page) {
31
32 //1、获取整个页面的内容:
33 //System.out.println("获取整个页面内容:"+page.getHtml().toString());
34
35 //2、使用xpath表达式过滤内容: 获取页面的内容
36 //System.out.println(page.getHtml().xpath("//*[@id=\"mainScreen\"]/div/div/div/div[1]/div[2]/a[6]").toString());
37 //System.out.println(page.getHtml().xpath("//*[@id=\"mainScreen\"]/div/div/div/div[1]/div[2]/a[6]/text()").toString());
38
39
40 //3、使用正则表达式获取有用的链接
41 //System.out.println("获取所有连接:"+page.getHtml().links().all());
42 List link1 = page.getHtml().regex("https://my.oschina.net/u/[0-9]{3,8}/blog/[0-9]{3,8}").all();
43 List link2 = page.getHtml().regex("https://my.oschina.net/[a-zA0-9_-]{2,20}/blog/[0-9]{3,8}").all();
44 link1.addAll(link2);
45 //System.out.println(link1);
46 //递归爬取: 一直爬取到没有为止
47 page.addTargetRequests(link1);
48
49
50 //======================================================================================================================
51 //======================================================================================================================
52 //======================================================================================================================
53 String title = page.getHtml().xpath("//*[@id=\"mainScreen\"]/div/div/div/div[2]/div[1]/div[2]/h2/text()").toString();
54 //把url往下传递
55 if(StringUtils.isNotBlank(title)) {
56 page.putField("title", title.trim());
57 }else {
58 //如果为空,跳过采集
59 page.setSkip(true);
60 }
61
62
63 }
64
65 /**
66 * 站点信息:休眠时间、重试次数等
67 */
68 @Override
69 public Site getSite() {
70 return site;
71 }
72
73
74 public static void main(String[] args) {
75 Spider.create(new MyPageProcessor()) //传入页面处理器
76 .addUrl("https://www.oschina.net/blog") //爬取页面的入口: 给Downloader使用的
77 .addPipeline(new ConsolePipeline()) //添加持久化策略: Pipeline使用
78 .addPipeline(new FilePipeline("G:\\webmagic"))//持久化到文件中
79 .addPipeline(new JsonFilePipeline("G:\\webmagic")) //持久化到json中
80 .addPipeline(new DBPipeline())//自定义pipeline
81 //.setScheduler(new QueueScheduler()) //内存队列
82 //.setScheduler(new FileCacheQueueScheduler("D:\\00_class\\112\\webmagic\\fileSchulder")) //不适用于分布式系统
83 .setScheduler(new RedisPriorityScheduler("192.168.23.1")) //以后用这种:适合分布式系统
84 .start();
85 }
86
87}
持久化到数据库中
1package com.mobaijun;
2
3import us.codecraft.webmagic.ResultItems;
4import us.codecraft.webmagic.Task;
5import us.codecraft.webmagic.pipeline.Pipeline;
6
7import java.util.HashMap;
8
9/**
10 * @Author:Auser·杰
11 * @DATE:2019/10/20 0:17
12 */
13//持久化到数据库的pipeline
14public class DBPipeline implements Pipeline {
15
16 @Override
17 public void process(ResultItems rs, Task task) {
18 System.out.println("持久化到数据库中:"+rs.get("title"));
19
20 System.out.println("\t\n");
21 System.out.println("\t\n");
22 }
23
24}
依次将爬取结果输入到磁盘中;
后面的代码感兴趣的小伙伴手敲一下,还是蛮有意思的