前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >WebMagic爬取指定内容和一些特性介绍(附演示代码)

WebMagic爬取指定内容和一些特性介绍(附演示代码)

作者头像
框架师
发布2019-11-04 03:14:22
2.1K0
发布2019-11-04 03:14:22
举报

一丶WebMagic:xpath爬取指定内容

 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}

结果:

三丶Pipeline:控制台、文件、定制输出

一般我们爬取的内容是不会放在控制台打印输出的,而是存储在磁盘空间或者是数据库中,下面通过代码来演示;

 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}

依次将爬取结果输入到磁盘中;

后面的代码感兴趣的小伙伴手敲一下,还是蛮有意思的

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 框架师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一丶WebMagic:xpath爬取指定内容
  • 二丶通过正则表达式过滤无效链接并爬取有效内容
  • 三丶Pipeline:控制台、文件、定制输出
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档