返回顶部
首页 > 资讯 > 后端开发 > Python >教你如何用Java简单爬取WebMagic
  • 713
分享到

教你如何用Java简单爬取WebMagic

2024-04-02 19:04:59 713人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

一、Java爬虫——WEBMagic  1.1 WebMagic总体架构图 1.2 WebMagic核心组件 1.2.1 Downloader 该组件负责从互联网上下载页

一、Java爬虫——WEBMagic

 1.1 WebMagic总体架构

WebMagic总体架构图

1.2 WebMagic核心组件

1.2.1 Downloader

该组件负责从互联网上下载页面。WebMagic默认使用Apache HttpClient作为下载工具

1.2.2 PageProcessor

该组件负责解析页面,根据我们的业务进行抽取信息。WebMagic使用jsoup作为html解析工具,并基于其开发了解析Xpath的工具Xsoup。

1.2.3 Scheduler

该组件负责管理待抓取的URL,以及去重的工作。WebMagic默认使用jdk内存队列管理URL,通过集合进行去重。

支持使用Redis进行分布式管理。

1.2.4 Pipeline

该组件负责抽取结果的处理,包括计算、持久化到文件、数据库等等。

1.2.5 数据流转对象

 1. Request

Request是对URL地址的一层封装,一个Request对应一个URL地址。

它是PageProcessor与Downloader交互的载体,也是PageProcessor控制Downloader唯一方式。

除了URL本身外,它还包含一个Key-Value结构的字段extra。你可以在extra中保存一些特殊的属性,然后在其他地方读取,以完成不同的功能。例如附加上一个页面的一些信息等。

2. Page

Page代表了从Downloader下载到的一个页面——可能是HTML,也可能是JSON或者其他文本格式的内容。

Page是WebMagic抽取过程的核心对象,它提供一些方法可供抽取、结果保存等。

3. ResultItems

ResultItems相当于一个Map,底层使用了LinkedHashMap进行存储,它保存PageProcessor处理的结果,供Pipeline使用。它的api与Map很类似,值得注意的是它有一个字段skip,若设置为true,则不被Pipeline处理,跳过。

1.2.6 Spider——WebMagic核心引擎

Spider是WebMagic内部流程的核心。Downloader、PageProcessor、Scheduler、Pipeline都是Spider的一个属性,这些属性是可以自由设置的,通过设置这个属性可以实现不同的功能。Spider也是WebMagic操作的入口,它封装了爬虫的创建、启动、停止、多线程等功能。

1.3 练习Demo

需求是爬取一篇厦门限行文章,文章来源:http://xm.bendibao.com/traffic/2018116/54311.shtm,具体需求如下:

1.删除文章中超链接

2.文章中的图片下载至本地

3.删除文章末尾:温馨提示...

1.3.1 定制Downloader

为预防页面失效,定制一个Downloader,当链接地址不存在时,打印日志


public class MyHttpClientDownloader extends HttpClientDownloader {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    
    @Override
    protected Page handleResponse(Request request, String charset, HttpResponse httpResponse, Task task) throws ioException {
        Page page = super.handleResponse(request, charset, httpResponse, task);
        if(httpResponse.getStatusLine().getStatusCode()!= ConstantsField.PAGE_STATUS_200){
            page.setDownloadSuccess(false);
            logger.warn("页面获取状态码错误,正在重试!");
        }
        return page;
    }
}

1.3.2 定制PageProcessor

该页面处理器实现了对页面的抽取,符合上面的需求。

将处理完成的数据添加进入:Page对象,并设置键分别为:imgListcontent


public class XmPageProcessor implements PageProcessor {

    
    private Site site = Site.me().setCycleRetryTimes(3).setSleepTime(1000);

    
    @Override
    public void process(Page page) {
        // 抽取页面文本数据
        Selectable selectable = page.getHtml().CSS(ConstantsField.PAGE_CSS_CONTENT);

        //处理图片
        List<String> pImgList = selectable.xpath(ConstantsField.XPATH_IMG).all();
        List<String> imgUrl = new ArrayList<>();
        if(pImgList.size()>0){
            Pattern compile = Pattern.compile(ConstantsField.REX_IMG_SRC);
            for (String img : pImgList) {
                Matcher matcher = compile.matcher(img);
                while (matcher.find()){
                    imgUrl.add(matcher.group(1));
                }
            }
        }
        if(imgUrl.size()>0){
            page.putField("imgList",imgUrl);
        }else {
            page.putField("imgList",null);
        }

        //对内容转换为StringBuilder
        String content = selectable.toString();
        StringBuilder stringBuilder = new StringBuilder(content);

        //处理超链接
        StringBuilder newString = dealLink(stringBuilder);

        //处理末尾
        int startIndex = newString.indexOf(ConstantsField.END_CONTENT);
        if(startIndex>0) {
            newString.delete(startIndex, stringBuilder.length());
            newString.append("</div>");
        }

        page.putField("content",newString.toString());
    }

    @Override
    public Site getSite() {
        return site;
    }

    
    private static StringBuilder dealLink(StringBuilder stringBuilder){
        StringBuilder newString = new StringBuilder(stringBuilder);
        int aindex = newString.indexOf("<a href");
        while (aIndex != -1){
            int pStart = newString.lastIndexOf("<p>", aIndex);
            int pEnd = (newString.indexOf("</p>", aIndex) + 4);
            newString.delete(pStart,pEnd);
            aIndex = newString.indexOf("<a href");
        }
        return newString;
    }
}

1.3.3 定制Pipeline

Pipeline是处理结果的地方,这里我们对结果进行存储文件的处理。网站文本存储为:stm格式,图片文本存储为其网站源文件的格式。


public class MyFilePipeline extends FilePersistentBase implements Pipeline {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private StringBuilder filepath;

    private MyFilePipeline() {
        this.setPath(ConstantsField.DEFAULT_SAVE_LOCATION);
    }

    public MyFilePipeline(String path) {
        if(path!=null){
            this.setPath(path);
        }else {
            new MyFilePipeline();
        }
        filepath = new StringBuilder().append(this.path).
                append(PATH_SEPERATOR).append(ConstantsField.FILE_NAME)
                .append(ConstantsField.FILE_POSTFIX);

    }

    @Override
    public void process(ResultItems resultItems, Task task) {
        //文件内容覆盖
        try(PrintWriter printWriter = new PrintWriter(new FileWriter(getFile(filepath.toString()),false))) {
            printWriter.write(resultItems.get("content").toString());
            logger.info("文件生成成功,存储地址为:"+filepath);

            //下载图片
            List<String> imgList = resultItems.get("imgList");
            if(imgList!=null&&imgList.size()>0){
                boolean dowload = DownloadImgUtils.download(imgList, this.getPath());
                if(dowload){
                    logger.info("图片下载成功,存储地址为:" + this.getPath());
                }
            }

        } catch (IOException e) {
            logger.error("输出文件出错:" + e.getCause().toString());
        }
    }
}

这里实现了网页存储为stm格式与图片存储,图片存储使用了如下工具类DownloadImgUtils


public class DownloadImgUtils {

    
    public static boolean download(List<String> imgList, String savePath) throws IOException {
        URL url;
        DataInputStream dataInputStream = null;
        FileOutputStream fileOutputStream = null;
        File file;
        try {
            for (String imgUrl : imgList) {
                //截取文件名
                Pattern pat=Pattern.compile(ConstantsField.REX_IMG_SUFFIX);
                Matcher mc=pat.matcher(imgUrl);
                while(mc.find()) {
                    String fileName= mc.group();
                    file = new File(savePath + fileName);
                    file.createNewFile();
                    fileOutputStream = new FileOutputStream(savePath + fileName);
                }

                url = new URL(imgUrl);
                dataInputStream = new DataInputStream(url.openStream());

                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int length;
                while ((length = dataInputStream.read(buffer))>0){
                    outputStream.write(buffer,0,length);
                }
                fileOutputStream.write(outputStream.toByteArray());
            }
            return true;
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            dataInputStream.close();
            fileOutputStream.close();
        }

        return false;
    }
}

1.3.4 启动类


public class WebMagicApplication {

    private String url;
    private String saveUrl;

    
    public WebMagicApplication() {
        this.url = ConstantsField.XM_BDB_URL;
        this.saveUrl = ConstantsField.DEFAULT_SAVE_LOCATION;
    }

    public WebMagicApplication(String url, String saveUrl) {
        this.url = url;
        this.saveUrl = saveUrl;
    }

    public void start(){
        Spider.create(new XmPageProcessor()).addUrl(this.url).addPipeline(new MyFilePipeline(this.saveUrl)).setDownloader(new MyHttpClientDownloader()).run();
    }

    public static void main(String[] args) {
        WebMagicApplication webMagicApplication = new WebMagicApplication("http://xm.bendibao.com/traffic/2018116/5431122.shtm","C:\\");
        webMagicApplication.start();
    }
}

这里启动类可以使用带参构造或无参构造,无参构造默认使用URL与存储地址为ConstantsField类中的XM_BDB_URL属性和DEFAULT_SAVE_LOCATION

练习中的ConstantsField具体如下:


public final class ConstantsField {
    
    public static final String PAGE_CSS_CONTENT = "div.content";

    
    public static final String END_CONTENT = "<div id=\"adInArticle\"></div>";

    
    public static final String XM_BDB_URL = "http://xm.bendibao.com/traffic/2018116/54311.shtm";

    
    public static final String DEFAULT_SAVE_LOCATION = "C:\\";

    
    public static final String FILE_NAME = "2021厦门限行最新消息(持续更新)";

    
    public static final String FILE_POSTFIX = ".stm";

    
    public static final int PAGE_STATUS_200 = 200;

    
    public static final String REX_IMG_SRC = "src\\s*=\\s*\"?(.*?)(\"|>|\\s+)";

    
    public static final String REX_IMG_SUFFIX = "[\\w]+[\\.](jpeg|jpg|png)";

    
    public static final String XPATH_IMG = "/img";
}

1.3.5 源码地址

练习Demo源码地址: https://gitee.com/Xiaoxinnolabi/web-magic/settings
WebMagic中文文档: http://webmagic.io/docs/zh/
WebMagic源码地址: https://GitHub.com/code4craft/webmagic/

到此这篇关于教你如何用Java简单爬取WebMagic的文章就介绍到这了,更多相关Java爬取WebMagic内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: 教你如何用Java简单爬取WebMagic

本文链接: https://lsjlt.com/news/129490.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 教你如何用Java简单爬取WebMagic
    一、Java爬虫——WebMagic  1.1 WebMagic总体架构图 1.2 WebMagic核心组件 1.2.1 Downloader 该组件负责从互联网上下载页...
    99+
    2024-04-02
  • 如何用六步教会你使用python爬虫爬取数据
    目录前言:python爬出六部曲第一步:安装requests库和BeautifulSoup库:第二步:获取爬虫所需的header和cookie:第三步:获取网页:第四步:解析网页:第...
    99+
    2024-04-02
  • 如何利用Node.js做简单的图片爬取
    目录介绍安装引入创建实例元素捕获下载图片结语介绍 爬虫的主要目的是收集互联网上公开的一些特定数据。利用这些数据我们可以能进行分析一些趋势对比,或者训练模型做深度学习等等。本期我们就将...
    99+
    2024-04-02
  • python爬虫之教你如何爬取地理数据
    目录一、shapely模块1、shapely2、point→Point类3、导入所需模块4、Point(1)、创建point,主要有以下三种方法(2)、point常用属性(3)、po...
    99+
    2024-04-02
  • 简单教你如何装win7系统
      当我们的电脑使用时间久了之后会出现各种小毛病,黑屏,蓝屏,系统奔溃,卡顿都是有可能的,这时我们就只能通过重装系统来解决问题,那么如何装win7系统呢接下来小编把重装win7系统的方法分享给大家,我们一起来看看吧。  如何装win7系统步...
    99+
    2023-07-12
  • Python爬虫之教你利用Scrapy爬取图片
    目录Scrapy下载图片项目介绍使用Scrapy下载图片项目创建项目预览创建爬虫文件项目组件介绍Scrapy爬虫流程介绍页面结构分析最终目录树项目运行爬取结果后记Scrapy下载图片...
    99+
    2024-04-02
  • 如何在java中使用WebMagic框架
    本篇文章为大家展示了如何在java中使用WebMagic框架,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. ...
    99+
    2023-06-14
  • 教你如何利用python3爬虫爬取漫画岛-非人哉漫画
        最近学了一点点python爬虫的知识,面向百度编程爬了一本小说之后感觉有点不满足,于是突发奇想尝试爬一本漫画下来看看。 一、效果展示   首先是我们想要爬取的漫画网页:htt...
    99+
    2024-04-02
  • 教你JS更简单的获取表单中数据(formdata)
    在文章正式开始之前呢,先介绍一个知识点,那就是var和let的区别,查看了各路大佬的文章,也经过各种尝试,最终得出的结果是,let声明的变量只在该变量对应的块中有效,有点局部变量的意...
    99+
    2023-05-20
    js获取表单数据 js formdata
  • 教你如何使用Python快速爬取需要的数据
    目录一、基础第三方库使用二、爬虫的网页抓取三、动态网页和静态网页的区分四、动态网页和静态网页的抓取一、基础第三方库使用 1.基本使用方法 """例""" from urllib ...
    99+
    2024-04-02
  • 教你如何使Python爬取酷我在线音乐
    目录前言获取歌曲信息列表请求参数分析请求代码获取歌曲下载链接免费歌曲付费歌曲请求代码后记前言 写这篇博客的初衷是加深自己对网络请求发送和响应的理解,仅供学习使用,请勿用于非法用途!文...
    99+
    2024-04-02
  • 教你如何用Python做人脸识别,简单易学!
    Python是一种计算机编程语言以及配套的软件工具和库。Python简单易学,代码十分简洁,它使用强制空白符作为缩进,这大大提高了Python的开发效率,使用Python能够在更短的时间内完成更多的工作。Python是一门开源的语言,并且P...
    99+
    2023-09-05
    python 开发语言
  • 一篇文章教会你使用java爬取想要的资源
    目录说明方法摘要常用的Element节点方法实战:爬取B站番剧Maven代码说明 简介: 你还在为想要的资源而获取不到而烦劳吗?你还在为你不会python而爬取不到资源而烦劳吗?没关...
    99+
    2024-04-02
  • 教你如何用python爬取王者荣耀月收入流水线
    目录前言一.App收入排行流水线1.1.获取数据1.2流水线可视化二.近一月日收入可视化2.1获取数据2.2可视化展示三.近一年月收入可视化3.1获取数据3.2可视化展示前言 王者荣...
    99+
    2024-04-02
  • 如何使用Java爬虫批量爬取图片
    目录Java爬取图片爬取思路具体步骤具体代码实体类 Picture 和 工具类 HeaderUtil下载类最重要的类:解析页面类 PictureSpider启动类 BootStrap...
    99+
    2023-05-15
    Java爬虫 Java爬虫批量 批量爬取图片
  • 教你用Java实现一个简单的代码生成器
    前言 逆向工程从数据库表直接生成代码,是日常开发中常用的敏捷开发手段,常见的例如:mybatis-plus的代码生成器等 为什么要自己写代码生成器呢?MP的生成器不香吗?香! 但是自...
    99+
    2024-04-02
  • Python中如何用最简单的办法爬取最好看的图片
    这篇文章给大家介绍Python中如何用最简单的办法爬取最好看的图片,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前言接下来我们一个很基本的BeautifulSoup爬虫库来写一下爬取图片的过程,下载并存储图片,相信大家...
    99+
    2023-06-02
  • 教你如何使用JAVA POI
    目录一、导入jar包二、导出三、导出一、导入jar包 所需jar包,在pom中添加如下坐标即可 <dependency> <groupId>org...
    99+
    2024-04-02
  • 如何用Java编写你自己的简单HTTP服务器
    如何用Java编写你自己的简单HTTP服务器,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。HTTP是个大协议,完整功能的HTTP服务器必须响应资源请求,将URL转换为本地系...
    99+
    2023-06-17
  • 教你使用Python写一个简单的JSONParser
    目录引言JSON TokenizerJSON Parser引言 最近在学习 Python 的正则表达式内容,我看的是官方的文档,在文档的最后有一个例子,勾起了我的兴趣。它是用正则表达...
    99+
    2023-05-14
    Python JSONParser 简单 JSONParser
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作