Java-网络爬虫(三)

news2024/11/19 19:43:46

文章目录

  • 前言
  • 一、爬虫的分类
  • 二、跳转页面的爬取
  • 三、网页去重
  • 四、综合案例
    • 1. 案例三


上篇:Java-网络爬虫(二)

前言

上篇文章介绍了 webMagic,通过一个简单的入门案例,对 webMagic 的核心对象和四大组件都做了简要的说明,以下内容则是继续对 webMagic 的讲解


一、爬虫的分类

爬虫按照系统结构和实现技术,大致可以分为以下几种类型:

通用网络爬虫(General Purpose Web Crawler)

也被称为全网爬虫,这种爬虫的爬取目标资源在全互联网中,爬取目标数据巨大。它主要用于为大型搜索引擎和门户网站采集数据。这类爬虫对于爬行速度和存储空间要求较高,对于爬行页面的顺序要求相对较低,同时由于待刷新的页面比较多,通常采用并行工作方式,但需要较长时间才能刷新一次页面,简单的说就是互联网上抓取所有数据。通用网络爬虫的基本构成包括初始 URL 集合、URL 队列、页面爬行模块、页面分析模块、页面数据库、链接过滤模块等。

聚焦网络爬虫(Focused Web Crawler)

也被称为主题网络爬虫,这种爬虫选择性地爬取那些与预先定义好的主题相关的页面。聚焦网络爬虫的目标是只抓取互联网上某一种数据。和通用网络爬虫相比,聚焦爬虫只需要爬行与主题相关的页面,极大地节省了硬件和网络资源,保存的页面也由于少量而更新快,还可以很好地满足一些特定人群对特定领域信息的需求。

量式网络爬虫(Incremental Web Crawler)

这种爬虫会不断爬取数据,但仅爬取新产生的或者已经发生变化的网页,它能够在一定程度上保证所爬行的页面是尽可能新的页面。和周期性爬行和刷新页面的网络爬虫相比,增量式爬虫只会在需要的时候爬行新产生或发生更新的页面,并不重新下载没有发生变化的页面,可有效减少数据下载量,及时更新已爬行的网页,减小时间和空间上的耗费,但是增加了爬行算法的复杂度和实现难度。

深层网络爬虫(Deep Web Crawler)

也被称为深网爬虫,这种爬虫主要抓取隐藏在搜索表单后的、不能通过静态链接获取的网页。这些页面只有当用户提交一些关键词才能获得。


二、跳转页面的爬取

在很多情况下,当我们爬取一个页面的信息时,要通过一些链接进入到其它的页面,进而继续爬取更多的信息

在这里插入图片描述

从上文介绍 webMagic 的原理中可以知道,只需要将待处理的 Request 放入 Scheduler 中就行了,Spider 会从 Scheduler 拉取 Requset 进行抓取,可以通过 page.addTargetRequests(Iterable<String> requests) 实现这一步,代码如下:

    @Override
    public void process(Page page) {

		// 解析处理
		...

	        // 待抓取的 URL
        List<String> waitUrls = new ArrayList<>();
        waitUrls.add("url_1");
        waitUrls.add("url_2");
        waitUrls.add("url_3");
        // 将待抓取的 URL 追加到 targetRequests 中
        page.addTargetRequests(waitUrls);
		
		// 持久化处理
		...
	}

同样我们可以去追寻源码,进入到 addTargetRequests(Iterable<String> requests) 方法中:

在这里插入图片描述

好像也没有看到将 Request 放入到 Scheduler 中,再看回 spider.run() 方法:

在这里插入图片描述

进入到 processRequest(Request request) 方法:

在这里插入图片描述

从上述源码可知,在运行完 process() 方法后会进入到一个 extractAndAddRequests() 方法来添加一些额外的 Requests,而这些 Requests 其实就是前面通过 page.addTargetRequests() 添加进去的,不妨再看看 extractAndAddRequests() 这个方法

在这里插入图片描述

到这里就可以看到通过 page.addTargetRequests() 这个方法确实会将待处理的 URL 全部推送至 Scheduler


三、网页去重

倘若出现了这么一种场景,在页面 web_1 中有跳转到页面 web_2URL,而在网页 web_2 中也存在着跳转到网页 web_1URL

在这里插入图片描述

那么就会出现这样一种现象,就是 web_1web_2 这两个页面会被无休止的重复解析,这显然是不合理的,所以我们需要记录下已被解析过的页面,让其不能重复解析,这就是页面的去重

对于页面的去重,可以采取很多种方式,这里我就列举三种常用的方法:

  • HashSet 去重:使用 Java 中的 HashSet 不能重复的特点进行去重
    • 优点:容易理解,使用方便
    • 缺点:占用内存大,性能较低
  • Redis 去重:使用 redis 的 set 进行去重
    • 优点:速度快,而且去重不会占用爬虫服务器的资源,可以处理更大数据量的数据爬取
    • 缺点:需要准备 redis 服务器,成本增加
  • 布隆过滤器(BloomFilter):使用布隆过滤器的特性进行去重
    • 优点:相比于 HashSet 去重更快,更加节省内存,也适用于大量数据的去重
    • 缺点:有误判的可能,没有重复可能会被判断为重复,但是重复数据一定会判定重复

关于布隆过滤器的原理可参见博客:Java-布隆过滤器的实现

实际上 webbMagic 提供的 Scheduler 组件已经帮我们解决了上述问题,Scheduler 不仅会将待抓取的 URL 放到队列中进行管理,还会对比已抓取的 URL 进行去重

webMagic 内置了几个常用的 Scheduler,如果只是本地执行规模比较小的爬虫,基本无需定制 Scheduler

说明备注
DuplicateRemovedScheduler抽象基类,提供了一些模板方法继承它可以实现自己的功能
QueueScheduler使用内存队列保存待抓取的 URL如果数据量比较庞大的话,可能会造成内存溢出
PriorityScheduler使用带有优先级的内存队列保存待抓取的 URL耗费内存较 QueueScheduler 更大,但是当设置了 request.priority 之后,只能使用 PriorityScheduler 才可使优先级生效
FileCacheQueueSchedulerwebMagic-extension 提供,使用文件保存抓取 URL,可以在关闭程序并下次启动时,从之前抓取到的 URL 继续抓取需要指定文件存放路径,会建立 urls.txtcursor.txt 两个文件
RedisSchedulerwebMagic-extension 提供,使用 redis 保存抓取队列,可进行多台机器同时合作抓取需要安装并启动 redis
RedisPrioritySchedulerwebMagic-extension 提供,使用 redis 保存抓取队列,可设置优先级需要安装并启动 redis

去重部分被单独抽象成了一个接口 — DuplicateRemover

public interface DuplicateRemover {

    boolean isDuplicate(Request var1, Task var2);

    void resetDuplicateCheck(Task var1);

    int getTotalRequestsCount(Task var1);
}

从而可以为同一个 Scheduler 选择不同的去重方式,以适配不同的需要,目前提供了两种去重方式:

说明
HashSetDuplicateRemover使用 HashSet 来进行去重,占用内存较大
BloomFilterDuplicateRemoverwebMagic-extension 提供,使用 BloomFilter 来进行去重,占用内存较小,但是可能漏抓页面

除了 RedisSchedulerRedisPriorityScheduler 是使用 redisset 进行去重,其它的 Scheduler 默认使用 HashSetDuplicateRemover 进行去重的

在这里插入图片描述
我们可以通过类图类验证,DuplicateRemovedScheduler 是其它的 Scheduler 的基类,在 DuplicateRemovedScheduler 中使用的就是 HashSetDuplicateRemover,所以其它的 Scheduler 也继承了这一点

在这里插入图片描述

但是 RedisScheduler 实现了 DuplicateRemover 接口,重写了其中的去重逻辑,使用 set 来存储 url,而 RedisPriorityScheduler 又继承了 RedisScheduler,所以这两个是使用了 redisset 进行去重的

在这里插入图片描述

如果需要使用到布隆过滤器进行去重,则需要进行设置

在设置之前还需要先添加 guava 依赖,因为 webMagic-extension 中使用的布隆过滤器是 guava 中的 BloomFilter

maven 导入 guava 依赖

<!-- guava -->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>33.0.0-jre</version>
</dependency>

代码设置 Scheduler 使用布隆过滤器

        // 创建 scheduler
        QueueScheduler scheduler = new QueueScheduler();
        // 设置 scheduler 使用布隆过滤器,预计存放一百万条数据
        scheduler.setDuplicateRemover(new BloomFilterDuplicateRemover(1000000));
        // Spider 设置 scheduler
        spider.setScheduler(scheduler);

四、综合案例

1. 案例三

下载食品营养成分查询平台的所有页面持久化到本地磁盘中

在这里插入图片描述

分析:

  • ① 如果需要爬到该网站的所有页面,就需要将每个页面的超链接放入待处理 URL
  • ② 对网页进行去重处理,可以使用布隆过滤器
  • ③ 要将网页内容持久化到本地磁盘可以使用 FilePipeline

代码如下:

import com.google.common.base.Charsets;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import us.codecraft.webmagic.Page;
import us.codecraft.webmagic.Site;
import us.codecraft.webmagic.Spider;
import us.codecraft.webmagic.pipeline.FilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.scheduler.BloomFilterDuplicateRemover;
import us.codecraft.webmagic.scheduler.QueueScheduler;
import us.codecraft.webmagic.selector.Html;
import java.util.Collections;
import java.util.List;

public class WebMagicDemo01 implements PageProcessor {

    @Override
    public void process(Page page) {

        // 获取当前页面的 Html 对象
        Html html = page.getHtml();

        // 获取页面上所有的链接
        List<String> links = html.links().all();
        // 放入待处理 url 中
        page.addTargetRequests(links);

        // 将 html 内容放置 resultItems 中
        page.putField("html", html.get());
    }

    @Override
    public Site getSite() {
        // 返回自定义 Site
        return Site.me()
                // 设置字符集
                .setCharset(Charsets.UTF_8.name())
                // 设置超时时间:5000(单位毫秒)
                .setTimeOut(5000)
                // 设置重试间隔时间:3000(单位毫秒)
                .setRetrySleepTime(3000)
                // 设置重试次数:5
                .setRetryTimes(5);
    }

    public static void main(String[] args) {

        // 创建 spider
        Spider spider = Spider.create(new WebMagicDemo01());

        // 创建 scheduler
        QueueScheduler scheduler = new QueueScheduler();
        // 设置 scheduler 使用布隆过滤器,预计存放一百万条数据
        scheduler.setDuplicateRemover(new BloomFilterDuplicateRemover(1000000));
        // Spider 设置 scheduler
        spider.setScheduler(scheduler);

        // 创建 filePipeline
        FilePipeline filePipeline = new FilePipeline();
        // 设置存放路径
        filePipeline.setPath("D:\\web-magic\\download-page");
        // Spider 设置 pipeline
        spider.setPipelines(Collections.singletonList(filePipeline));

        // 设置初始 URL
        spider.addUrl("http://yycx.yybq.net/");

        // 开启 2 个线程
        spider.thread(2);
        // 异步爬取
        spider.runAsync();
    }
}

可以看到指定文件夹下就开始下载这个网站的页面文件了

在这里插入图片描述

将下载的 html 文件内容和网页源码对比,可以看见基本上是一致的,不过多了一点内容

在这里插入图片描述

在游览器上打开下载的 html 文件

在这里插入图片描述

可以看到虽然下载的 html 文件中的内容和网页源代码几乎一样,但是却没有样式,图片也显示不了,链接跳转过去也是 404,原因是在源码中有关资源的路径使用的都是相对路径,而本地没有这些资源当然访问不了

如果想要解决上述问题:

  • ① 去除多余的内容
  • ② 游览器打开下载的 html 文件,资源部分未能加载

解决方案:

  • 问题 ①:重写 FilePipeline 去除打印多余部分的代码
  • 问题 ②:将有关资源的路径前全部加上起始网页地址

改进后代码:

import com.google.common.base.Charsets;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import us.codecraft.webmagic.*;
import us.codecraft.webmagic.pipeline.FilePipeline;
import us.codecraft.webmagic.processor.PageProcessor;
import us.codecraft.webmagic.scheduler.BloomFilterDuplicateRemover;
import us.codecraft.webmagic.scheduler.QueueScheduler;
import us.codecraft.webmagic.selector.Html;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class WebMagicDemo01 implements PageProcessor {

    @Override
    public void process(Page page) {

        // 获取当前页面的 Html 对象
        Html html = page.getHtml();

        // 获取页面上所有的链接
        List<String> links = html.links().all();
        // 放入待处理 url 中
        page.addTargetRequests(links);


        // 获取所有的 src 属性
        Document document = html.getDocument();
        Elements srcElements = document.select("script,img");
        for (Element element : srcElements) {
            if (StringUtils.isNotBlank(element.baseUri())) {
                String src = element.attr("abs:src");
                // 重新设置属性
                element.attr("src", src);
            }
        }

        // 获取所有的标签属性
        Elements aElements = document.select("a,link");
        for (Element element : aElements) {
            if (StringUtils.isNotBlank(element.baseUri())) {
                String href = element.attr("abs:href");
                // 重新设置属性
                element.attr("href", href);
            }
        }

        // 将 html 内容放置 resultItems 中
        page.putField("html", html.get());
    }

    @Override
    public Site getSite() {
        // 返回自定义 Site
        return Site.me()
                // 设置字符集
                .setCharset(Charsets.UTF_8.name())
                // 设置超时时间:5000(单位毫秒)
                .setTimeOut(5000)
                // 设置重试间隔时间:3000(单位毫秒)
                .setRetrySleepTime(3000)
                // 设置重试次数:5
                .setRetryTimes(5);
    }

    public static void main(String[] args) {

        // 创建 spider
        Spider spider = Spider.create(new WebMagicDemo01());

        // 创建 scheduler
        QueueScheduler scheduler = new QueueScheduler();
        // 设置 scheduler 使用布隆过滤器,预计存放一百万条数据
        scheduler.setDuplicateRemover(new BloomFilterDuplicateRemover(1000000));
        // Spider 设置 scheduler
        spider.setScheduler(scheduler);

        // 创建 filePipeline
        FilePipeline filePipeline = new MyFilePipeline();
        // 设置存放路径
        filePipeline.setPath("D:\\web-magic\\download-page");
        // Spider 设置 pipeline
        spider.setPipelines(Collections.singletonList(filePipeline));

        // 设置初始 URL
        spider.addUrl("http://yycx.yybq.net/");

        // 开启 2 个线程
        spider.thread(2);
        // 异步爬取
        spider.runAsync();
    }
}

/**
 * 继承 FilePipeline
 */
class MyFilePipeline extends FilePipeline {

    /**
     * 重写 FilePipeline 中的 process 方法
     * 去除打印多余部分的代码
     */
    @SuppressWarnings("all")
    public void process(ResultItems resultItems, Task task) {
        String path = this.path + PATH_SEPERATOR + task.getUUID() + PATH_SEPERATOR;

        try {
            PrintWriter printWriter = new PrintWriter(new OutputStreamWriter(new FileOutputStream(this.getFile(path + DigestUtils.md5Hex(resultItems.getRequest().getUrl()) + ".html")), "UTF-8"));
            Iterator var5 = resultItems.getAll().entrySet().iterator();

            while(true) {
                while(var5.hasNext()) {
                    Map.Entry<String, Object> entry = (Map.Entry)var5.next();
                    if (entry.getValue() instanceof Iterable) {
                        Iterable value = (Iterable)entry.getValue();
                        Iterator var8 = value.iterator();

                        while(var8.hasNext()) {
                            Object o = var8.next();
                            printWriter.println(o);
                        }
                    } else {
                        printWriter.println((String)entry.getValue());
                    }
                }
                printWriter.close();
                break;
            }
        } catch (IOException var10) {
            var10.printStackTrace();
        }
    }
}

再使用游览器打开新下载好的 html 文件就会能看到,其样式也官方网站的效果一样了

在这里插入图片描述

PS:以上案例只做学习爬虫使用,切勿恶意攻击他人网站

上篇:Java-网络爬虫(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1389637.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

不是人才用不起,而是AI巡检更有性价比!

在许多行业中&#xff0c;如煤炭、电力、化工等&#xff0c;安全生产是至关重要的。这就需要通过巡检&#xff0c;对设备运行状态进行实时监测&#xff0c;及时发现并处理潜在的安全隐患&#xff0c;从而降低事故发生的概率。但是传统的巡检方式通常依赖于人工进行&#xff0c;…

odoo17 | Qweb模板简介

前言 到目前为止&#xff0c;我们的房地产模块的界面设计还相当有限。构建列表视图很简单&#xff0c;因为只需要字段列表。表单视图也是如此&#xff1a;尽管使用了几个标签&#xff0c;如 <group>标签或 <page>标签 &#xff0c;但在设计方面几乎没什么可做的。…

【Java数据结构】04-图(Prim,Kruskal,Dijkstra,topo)

5 图 推荐辅助理解 【视频讲解】bilibili Dijkstra Prim 【手动可视化】Algorithm Visualizer &#xff08;https://algorithm-visualizer.org/&#xff09; 【手动可视化】Data Structure Visualizations (https://www.cs.usfca.edu/~galles/visualization/Algorithms.ht…

Python 捕获异常(Try Except Exception)

目录 前言 常见的十类异常类型&#xff1a; try...except...else语句 格式 示例1 示例2 捕获所有异常&#xff08;常用&#xff09; 格式 示例 try...except...finally语句 格式 示例 前言 异常捕获就是针对某一部分可能出错的代码&#xff0c;在运行期间一旦出现…

免费开源OCR 软件Umi-OCR

Umi-OCR 是一款免费、开源、可批量的离线 OCR 软件&#xff0c;基于 PaddleOCR&#xff0c;适用于 Windows10/11 平台 免费&#xff1a;本项目所有代码开源&#xff0c;完全免费。方便&#xff1a;解压即用&#xff0c;离线运行&#xff0c;无需网络。高效&#xff1a;自带高效…

Dhcp中继ensp

拓扑图 <Huawei>system-view [Huawei]sysname SW1 [SW1]vlan batch 10 20 [SW1]int e0/0/1 #配置access接口 [SW1-Ethernet0/0/1]port link-type access [SW1-Ethernet0/0/1]port default vlan 10 [SW1-Etherne…

基于4G数采终端的供热管网在线监测方案

我国大部地区全面进入到冬季&#xff0c;北方各地已开启冬季供暖&#xff0c;以保障居民生活所需。由于城市化的发展&#xff0c;城市内各供热区域愈发分散、供热管道漫长、供热环境复杂&#xff0c;对于供热管网及换热站点的监测和维护提出了诸多挑战。 方案介绍 针对提高供热…

0、C++预备知识

文章目录 C与C语言为什么要学习CC为什么难学c值得学习的新特征C参考书籍开发工具 可移植性和标准程序创建的技巧编译和链接 C与C语言 C是一种计算机高级程序设计语言&#xff0c;C既可以进行C语言的过程化程序设计&#xff0c;又可以进行以抽象数据类型为特点的基于对象的程序…

强化学习11——DQN算法

DQN算法的全称为&#xff0c;Deep Q-Network&#xff0c;即在Q-learning算法的基础上引用深度神经网络来近似动作函数 Q ( s , a ) Q(s,a) Q(s,a) 。对于传统的Q-learning&#xff0c;当状态或动作数量特别大的时候&#xff0c;如处理一张图片&#xff0c;假设为 210 160 3 …

Android性能优化 | DEX 布局优化和启动配置文件

Android性能优化 | DEX 布局优化和启动配置文件 引言 使用DEX布局优化和启动配置文件是优化Android应用性能的有效途径。DEX布局优化可以通过优化应用程序中的DEX文件布局&#xff0c;从而加快Android应用的启动速度和执行速度。启动配置文件则提供了一种灵活的方式来控制应用…

SDRAM小项目——命令解析模块

简单介绍&#xff1a; 在FPGA中实现命令解析模块&#xff0c;命令解析模块的用来把pc端传入FPGA中的数据分解为所需要的数据和触发命令&#xff0c;虽然代码不多&#xff0c;但是却十分重要。 SDRAM的整体结构如下&#xff0c;可以看出&#xff0c;命令解析模块cmd_decode负责…

知存科技助力AI应用落地:WTMDK2101-ZT1评估板实地评测与性能揭秘

文章目录 一、前言二、深入了解存算一体技术2.1 什么是存算一体2.2 存算一体技术发展历程2.3 基于不同存储介质的存内计算芯片性能比较 三、国产存算一体&#xff0c;重大进展3.1 知存科技&#xff1a;我国存算一体领域的研发领导者 四、知存科技新型 WTM2101 SOC 评估板使用评…

【RTOS】快速体验FreeRTOS所有常用API(9)中断管理

目录 九、中断管理9.1 基本概念9.2 两套API9.3 中断服务程序 九、中断管理 该部分暂无代码 9.1 基本概念 FreeRTOS中的中断管理主要涉及&#xff1a;两套API、中断服务编写 不能阻塞、不能处理耗时任务ISR的优先级高于任务&#xff1a;即使是优先级最低的中断&#xff0c;它的…

【小黑嵌入式系统第十五课】μC/OS-III程序设计基础(四)——消息队列(工作方式数据通信生产者消费者模型)、动态内存管理、定时器管理

上一课&#xff1a; 【小黑嵌入式系统第十四课】μC/OS-III程序设计基础&#xff08;三&#xff09;——信号量&#xff08;任务同步&资源同步&#xff09;、事件标记组&#xff08;与&或&多个任务&#xff09; 前些天发现了一个巨牛的人工智能学习网站&#xff0c…

美媒:OpenAI删除了禁止其技术被用于军事用途的条款

据美国调查新闻网站“拦截者”&#xff08;The Intercept&#xff09;1月12日报道&#xff0c;美国知名人工智能企业、ChatGPT母公司OpenAI近日悄悄修改了其产品的使用条款&#xff0c;删除了禁止将OpenAI技术用于军事用途的条文。 报道称&#xff0c;在今年1月10日之前&#…

Springboot+vue的智能无人仓库管理(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的智能无人仓库管理&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的智能无人仓库管理&#xff0c;采用M&#xff08…

基于Springboot的私人健身与教练预约管理系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的私人健身与教练预约管理系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三…

java基础:求数组的和以及平均数案例分析

/* * * 解题思路&#xff1a;首先定义一个包含数字的数组hens&#xff0c; * 然后使用循环遍历数组中的每个元素&#xff0c;并将其累加到sum变量中。 * 最后&#xff0c;将sum除以数组长度得到平均值avg。最终将结果打印输出到控制台。*/ 代码如下&#xff1a; package idea;…

机器学习算法实战案例:GRU 实现多变量多步光伏预测

文章目录 1 数据处理1.1 数据集简介1.2 导入库文件1.3 数据集处理1.4 训练数据构造 2 模型训练与预测2.1 模型训练2.2 模型多步预测2.3 预测可视化 答疑&技术交流机器学习算法实战案例系列 1 数据处理 1.1 数据集简介 实验数据集采用数据集7&#xff1a;常州普利司通光伏…

[linux]同步缓冲区数据到flash

一、需求 由于linux自身策略问题&#xff0c;在某些情况下需主动同步数据到flash。 二、方案 同步数据的两种方式&#xff1a;sync和fsync 2.1sync 将整个缓冲区同步至flash。性能较差。 2.2fsync -d [file] 将某一文件的数据同步至flash。 三、应用实例 3.1sync 3.2f…