[网络爬虫] Jsoup : HTML 解析工具

news2024/12/12 5:16:02

1 概述

简介

  • Jsoup是一款基于Java的HTML解析器,它提供了一种简单、灵活且易于使用的API,用于从URL、文件或字符串中解析HTML文档。它可以帮助开发人员从HTML文档中提取数据、操作DOM元素、处理表单提交等。

主要特点

Jsoup的主要特点包括:

  • 简单易用:Jsoup提供了一系列简单的API,使得解析HTML变得非常容易。开发人员可以使用类似于jQuery的选择器语法来选择DOM元素,从而方便地提取所需的数据。
  • 强大的HTML处理能力:Jsoup支持HTML5标准,并且能够处理不完整或损坏的HTML文档。它可以自动修复HTML中的错误,并且在解析过程中保留原始的HTML结构。
  • 安全可靠:Jsoup内置了防止XSS攻击的机制,可以自动过滤恶意的HTML标签和属性,保证解析过程的安全性。
  • 支持CSS选择器:Jsoup支持使用CSS选择器来选择DOM元素,这使得开发人员可以更加灵活地定位和操作HTML文档中的元素。
  • 与Java集成:Jsoup是基于Java开发的,可以与Java程序无缝集成。开发人员可以使用Java的各种特性和库来处理解析后的数据。

应用场景

Jsoup 在大数据、云计算领域的应用场景包括但不限于:

  • 网页数据抓取: Jsoup可以帮助开发人员从网页中提取所需的数据,例如爬取新闻、商品信息等。通过解析HTML文档,可以快速准确地获取所需的数据。
  • 数据清洗与处理: 在云计算中,大量的数据需要进行清洗和处理。Jsoup可以帮助开发人员解析HTML文档,提取出需要的数据,并进行进一步的处理和分析。
  • 网页内容分析: Jsoup可以帮助开发人员对网页内容进行分析,例如提取关键词、统计标签出现次数等。这对于搜索引擎优化、网页分析等领域非常有用。

竞品

爬虫解析HTML文档的工具有:

  • [java] Jsoup
  • GitHub - jhy/jsoup: jsoup: the Java HTML parser, built for HTML editing, cleaning, scraping, and XSS safety.
  • https://jsoup.org/
  • https://mvnrepository.com/artifact/org.jsoup/jsoup/1.12.2
  • [python] Beautiful Jsoup
  • Beautiful Soup: We called him Tortoise because he taught us.
  • GitHub - DeronW/beautifulsoup at v4.4.0
  • https://beautifulsoup.readthedocs.io/
  • https://beautifulsoup.readthedocs.io/zh-cn/v4.4.0/

回到顶部(Back to Top)

2 使用指南

  • 本章节,基于 1.14.3 版本

依赖引入

<!-- https://mvnrepository.com/artifact/org.jsoup/jsoup --> 
<dependency>     
	<groupId>org.jsoup</groupId>     
	<artifactId>jsoup</artifactId>
    <!-- 1.12.2 / 1.14.3 / 1.17.2 -->	
	<version>1.14.3</version> 
</dependency>

核心 API

org.jsoup.Jsoup

package org.jsoup;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.annotation.Nullable;
import org.jsoup.helper.DataUtil;
import org.jsoup.helper.HttpConnection;
import org.jsoup.nodes.Document;
import org.jsoup.parser.Parser;
import org.jsoup.safety.Cleaner;
import org.jsoup.safety.Safelist;
import org.jsoup.safety.Whitelist;

public class Jsoup {
    private Jsoup() {
    }

    public static Document parse(String html, String baseUri) {
        return Parser.parse(html, baseUri);
    }

    public static Document parse(String html, String baseUri, Parser parser) {
        return parser.parseInput(html, baseUri);
    }

    public static Document parse(String html, Parser parser) {
        return parser.parseInput(html, "");
    }

    public static Document parse(String html) {
        return Parser.parse(html, "");
    }

    public static Connection connect(String url) {
        return HttpConnection.connect(url);
    }

    public static Connection newSession() {
        return new HttpConnection();
    }

    public static Document parse(File file, @Nullable String charsetName, String baseUri) throws IOException {
        return DataUtil.load(file, charsetName, baseUri);
    }

    public static Document parse(File file, @Nullable String charsetName) throws IOException {
        return DataUtil.load(file, charsetName, file.getAbsolutePath());
    }

    public static Document parse(File file, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
        return DataUtil.load(file, charsetName, baseUri, parser);
    }

    public static Document parse(InputStream in, @Nullable String charsetName, String baseUri) throws IOException {
        return DataUtil.load(in, charsetName, baseUri);
    }

    public static Document parse(InputStream in, @Nullable String charsetName, String baseUri, Parser parser) throws IOException {
        return DataUtil.load(in, charsetName, baseUri, parser);
    }

    public static Document parseBodyFragment(String bodyHtml, String baseUri) {
        return Parser.parseBodyFragment(bodyHtml, baseUri);
    }

    public static Document parseBodyFragment(String bodyHtml) {
        return Parser.parseBodyFragment(bodyHtml, "");
    }

    public static Document parse(URL url, int timeoutMillis) throws IOException {
        Connection con = HttpConnection.connect(url);
        con.timeout(timeoutMillis);
        return con.get();
    }

    public static String clean(String bodyHtml, String baseUri, Safelist safelist) {
        Document dirty = parseBodyFragment(bodyHtml, baseUri);
        Cleaner cleaner = new Cleaner(safelist);
        Document clean = cleaner.clean(dirty);
        return clean.body().html();
    }

    /** @deprecated */
    @Deprecated
    public static String clean(String bodyHtml, String baseUri, Whitelist safelist) {
        return clean(bodyHtml, baseUri, (Safelist)safelist);
    }

    public static String clean(String bodyHtml, Safelist safelist) {
        return clean(bodyHtml, "", safelist);
    }

    /** @deprecated */
    @Deprecated
    public static String clean(String bodyHtml, Whitelist safelist) {
        return clean(bodyHtml, (Safelist)safelist);
    }

    public static String clean(String bodyHtml, String baseUri, Safelist safelist, Document.OutputSettings outputSettings) {
        Document dirty = parseBodyFragment(bodyHtml, baseUri);
        Cleaner cleaner = new Cleaner(safelist);
        Document clean = cleaner.clean(dirty);
        clean.outputSettings(outputSettings);
        return clean.body().html();
    }

    /** @deprecated */
    @Deprecated
    public static String clean(String bodyHtml, String baseUri, Whitelist safelist, Document.OutputSettings outputSettings) {
        return clean(bodyHtml, baseUri, (Safelist)safelist, outputSettings);
    }

    public static boolean isValid(String bodyHtml, Safelist safelist) {
        return (new Cleaner(safelist)).isValidBodyHtml(bodyHtml);
    }

    /** @deprecated */
    @Deprecated
    public static boolean isValid(String bodyHtml, Whitelist safelist) {
        return isValid(bodyHtml, (Safelist)safelist);
    }
}

org.jsoup.nodes.Node

关键 API
  • Jsoup遍历DOM树的方法
  • 根据id查找元素: getElementById(String id)
  • 根据标签查找元素: getElementsByTag(String tag)
  • 根据class查找元素: getElementsByClass(String className)
  • 根据属性查找元素: getElementsByAttribute(String key)
  • 兄弟遍历方法: siblingElements(), firstElementSibling(), lastElementSibling(); nextElementSibling(), previousElementSibling()
  • 层级之间遍历: parent(), children(), child(int index)

这些方法会返回Element或者Elements节点对象,这些对象可以使用下面的方法获取一些属性:

  • attr(String key): 获取某个属性值
  • attributes(): 获取节点的所有属性
  • id(): 获取节点的id
  • className(): 获取当前节点的class名称
  • classNames(): 获取当前节点的所有class名称
  • text(): 获取当前节点的textNode内容
  • html(): 获取当前节点的 inner HTML
  • outerHtml(): 获取当前节点的 outer HTML
  • data(): 获取当前节点的内容,用于script或者style标签等
  • tag(): 获取标签
  • tagName(): 获取当前节点的标签名称

有了这些API,就像 JQuery 一样很便利的操作DOM。

  • Jsoup也支持修改DOM树结构:
  • text(String value): 设置内容
  • html(String value): 直接替换HTML结构
  • append(String html): 元素后面添加节点
  • prepend(String html): 元素前面添加节点
  • appendText(String text), prependText(String text)
  • appendElement(String tagName), prependElement(String tagName)
源码
package org.jsoup.nodes;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import javax.annotation.Nullable;
import org.jsoup.SerializationException;
import org.jsoup.helper.Validate;
import org.jsoup.internal.StringUtil;
import org.jsoup.select.NodeFilter;
import org.jsoup.select.NodeTraversor;
import org.jsoup.select.NodeVisitor;

public abstract class Node implements Cloneable {
    static final List<Node> EmptyNodes = Collections.emptyList();
    static final String EmptyString = "";
    @Nullable
    Node parentNode;
    int siblingIndex;

    protected Node() {
    }

    public abstract String nodeName();

    protected abstract boolean hasAttributes();

    public boolean hasParent() {
        return this.parentNode != null;
    }

    public String attr(String attributeKey) {
		...
	}
	
    public abstract Attributes attributes();
	
    public int attributesSize() {
        return this.hasAttributes() ? this.attributes().size() : 0;
    }

    public Node attr(String attributeKey, String attributeValue) {
        attributeKey = NodeUtils.parser(this).settings().normalizeAttribute(attributeKey);
        this.attributes().putIgnoreCase(attributeKey, attributeValue);
        return this;
    }

    public boolean hasAttr(String attributeKey) {
        Validate.notNull(attributeKey);
        if (!this.hasAttributes()) {
            return false;
        } else {
            if (attributeKey.startsWith("abs:")) {
                String key = attributeKey.substring("abs:".length());
                if (this.attributes().hasKeyIgnoreCase(key) && !this.absUrl(key).isEmpty()) {
                    return true;
                }
            }

            return this.attributes().hasKeyIgnoreCase(attributeKey);
        }
    }

    public Node removeAttr(String attributeKey) {
        Validate.notNull(attributeKey);
        if (this.hasAttributes()) {
            this.attributes().removeIgnoreCase(attributeKey);
        }

        return this;
    }

    public Node clearAttributes() {
        if (this.hasAttributes()) {
            Iterator<Attribute> it = this.attributes().iterator();

            while(it.hasNext()) {
                it.next();
                it.remove();
            }
        }

        return this;
    }

    public abstract String baseUri();

    protected abstract void doSetBaseUri(String var1);

    public void setBaseUri(String baseUri) {
        Validate.notNull(baseUri);
        this.doSetBaseUri(baseUri);
    }

    public String absUrl(String attributeKey) {
        Validate.notEmpty(attributeKey);
        return this.hasAttributes() && this.attributes().hasKeyIgnoreCase(attributeKey) ? StringUtil.resolve(this.baseUri(), this.attributes().getIgnoreCase(attributeKey)) : "";
    }

    protected abstract List<Node> ensureChildNodes();

    public Node childNode(int index) {
        return (Node)this.ensureChildNodes().get(index);
    }

    public List<Node> childNodes() {
        if (this.childNodeSize() == 0) {
            return EmptyNodes;
        } else {
            List<Node> children = this.ensureChildNodes();
            List<Node> rewrap = new ArrayList(children.size());
            rewrap.addAll(children);
            return Collections.unmodifiableList(rewrap);
        }
    }

    public List<Node> childNodesCopy() {
        List<Node> nodes = this.ensureChildNodes();
        ArrayList<Node> children = new ArrayList(nodes.size());
        Iterator var3 = nodes.iterator();

        while(var3.hasNext()) {
            Node node = (Node)var3.next();
            children.add(node.clone());
        }

        return children;
    }

    public abstract int childNodeSize();

    protected Node[] childNodesAsArray() {
        return (Node[])this.ensureChildNodes().toArray(new Node[0]);
    }

    public abstract Node empty();

    @Nullable
    public Node parent() {
        return this.parentNode;
    }

    @Nullable
    public final Node parentNode() {
        return this.parentNode;
    }

    public Node root() {
        Node node;
        for(node = this; node.parentNode != null; node = node.parentNode) {
        }

        return node;
    }

    @Nullable
    public Document ownerDocument() {
        Node root = this.root();
        return root instanceof Document ? (Document)root : null;
    }

    public void remove() {
        Validate.notNull(this.parentNode);
        this.parentNode.removeChild(this);
    }

    public Node before(String html) {
        this.addSiblingHtml(this.siblingIndex, html);
        return this;
    }

    public Node before(Node node) {
        Validate.notNull(node);
        Validate.notNull(this.parentNode);
        this.parentNode.addChildren(this.siblingIndex, node);
        return this;
    }

    public Node after(String html) {
        this.addSiblingHtml(this.siblingIndex + 1, html);
        return this;
    }

    public Node after(Node node) {
        Validate.notNull(node);
        Validate.notNull(this.parentNode);
        this.parentNode.addChildren(this.siblingIndex + 1, node);
        return this;
    }

    private void addSiblingHtml(int index, String html) {
        Validate.notNull(html);
        Validate.notNull(this.parentNode);
        Element context = this.parent() instanceof Element ? (Element)this.parent() : null;
        List<Node> nodes = NodeUtils.parser(this).parseFragmentInput(html, context, this.baseUri());
        this.parentNode.addChildren(index, (Node[])nodes.toArray(new Node[0]));
    }

    public Node wrap(String html) {
        Validate.notEmpty(html);
        Element context = this.parentNode != null && this.parentNode instanceof Element ? (Element)this.parentNode : (this instanceof Element ? (Element)this : null);
        List<Node> wrapChildren = NodeUtils.parser(this).parseFragmentInput(html, context, this.baseUri());
        Node wrapNode = (Node)wrapChildren.get(0);
        if (!(wrapNode instanceof Element)) {
            return this;
        } else {
            Element wrap = (Element)wrapNode;
            Element deepest = this.getDeepChild(wrap);
            if (this.parentNode != null) {
                this.parentNode.replaceChild(this, wrap);
            }

            deepest.addChildren(new Node[]{this});
            if (wrapChildren.size() > 0) {
                for(int i = 0; i < wrapChildren.size(); ++i) {
                    Node remainder = (Node)wrapChildren.get(i);
                    if (wrap != remainder) {
                        if (remainder.parentNode != null) {
                            remainder.parentNode.removeChild(remainder);
                        }

                        wrap.after(remainder);
                    }
                }
            }

            return this;
        }
    }

    @Nullable
    public Node unwrap() {
        Validate.notNull(this.parentNode);
        List<Node> childNodes = this.ensureChildNodes();
        Node firstChild = childNodes.size() > 0 ? (Node)childNodes.get(0) : null;
        this.parentNode.addChildren(this.siblingIndex, this.childNodesAsArray());
        this.remove();
        return firstChild;
    }

    private Element getDeepChild(Element el) {
        List<Element> children = el.children();
        return children.size() > 0 ? this.getDeepChild((Element)children.get(0)) : el;
    }

    void nodelistChanged() {
    }

    public void replaceWith(Node in) {
        Validate.notNull(in);
        Validate.notNull(this.parentNode);
        this.parentNode.replaceChild(this, in);
    }

    protected void setParentNode(Node parentNode) {
        Validate.notNull(parentNode);
        if (this.parentNode != null) {
            this.parentNode.removeChild(this);
        }

        this.parentNode = parentNode;
    }

    protected void replaceChild(Node out, Node in) {
        Validate.isTrue(out.parentNode == this);
        Validate.notNull(in);
        if (in.parentNode != null) {
            in.parentNode.removeChild(in);
        }

        int index = out.siblingIndex;
        this.ensureChildNodes().set(index, in);
        in.parentNode = this;
        in.setSiblingIndex(index);
        out.parentNode = null;
    }

    protected void removeChild(Node out) {
        Validate.isTrue(out.parentNode == this);
        int index = out.siblingIndex;
        this.ensureChildNodes().remove(index);
        this.reindexChildren(index);
        out.parentNode = null;
    }

    protected void addChildren(Node... children) {
        List<Node> nodes = this.ensureChildNodes();
        Node[] var3 = children;
        int var4 = children.length;

        for(int var5 = 0; var5 < var4; ++var5) {
            Node child = var3[var5];
            this.reparentChild(child);
            nodes.add(child);
            child.setSiblingIndex(nodes.size() - 1);
        }

    }

    protected void addChildren(int index, Node... children) {
		...
	}

    protected void reparentChild(Node child) {
        child.setParentNode(this);
    }

    private void reindexChildren(int start) {
        if (this.childNodeSize() != 0) {
            List<Node> childNodes = this.ensureChildNodes();

            for(int i = start; i < childNodes.size(); ++i) {
                ((Node)childNodes.get(i)).setSiblingIndex(i);
            }

        }
    }

    public List<Node> siblingNodes() {
        if (this.parentNode == null) {
            return Collections.emptyList();
        } else {
            List<Node> nodes = this.parentNode.ensureChildNodes();
            List<Node> siblings = new ArrayList(nodes.size() - 1);
            Iterator var3 = nodes.iterator();

            while(var3.hasNext()) {
                Node node = (Node)var3.next();
                if (node != this) {
                    siblings.add(node);
                }
            }

            return siblings;
        }
    }

    @Nullable
    public Node nextSibling() {
        if (this.parentNode == null) {
            return null;
        } else {
            List<Node> siblings = this.parentNode.ensureChildNodes();
            int index = this.siblingIndex + 1;
            return siblings.size() > index ? (Node)siblings.get(index) : null;
        }
    }

    @Nullable
    public Node previousSibling() {
        if (this.parentNode == null) {
            return null;
        } else {
            return this.siblingIndex > 0 ? (Node)this.parentNode.ensureChildNodes().get(this.siblingIndex - 1) : null;
        }
    }

    public int siblingIndex() {
        return this.siblingIndex;
    }

    protected void setSiblingIndex(int siblingIndex) {
        this.siblingIndex = siblingIndex;
    }

    public Node traverse(NodeVisitor nodeVisitor) {
        Validate.notNull(nodeVisitor);
        NodeTraversor.traverse(nodeVisitor, this);
        return this;
    }

    public Node filter(NodeFilter nodeFilter) {
        Validate.notNull(nodeFilter);
        NodeTraversor.filter(nodeFilter, this);
        return this;
    }

    public String outerHtml() {
        StringBuilder accum = StringUtil.borrowBuilder();
        this.outerHtml(accum);
        return StringUtil.releaseBuilder(accum);
    }

    protected void outerHtml(Appendable accum) {
        NodeTraversor.traverse(new OuterHtmlVisitor(accum, NodeUtils.outputSettings(this)), this);
    }

    abstract void outerHtmlHead(Appendable var1, int var2, Document.OutputSettings var3) throws IOException;

    abstract void outerHtmlTail(Appendable var1, int var2, Document.OutputSettings var3) throws IOException;

    public <T extends Appendable> T html(T appendable) {
        this.outerHtml(appendable);
        return appendable;
    }

    public String toString() {
        return this.outerHtml();
    }

    protected void indent(Appendable accum, int depth, Document.OutputSettings out) throws IOException {
        accum.append('\n').append(StringUtil.padding(depth * out.indentAmount()));
    }

    public boolean equals(@Nullable Object o) {
        return this == o;
    }

    public int hashCode() {
        return super.hashCode();
    }

    public boolean hasSameValue(@Nullable Object o) {
        if (this == o) {
            return true;
        } else {
            return o != null && this.getClass() == o.getClass() ? this.outerHtml().equals(((Node)o).outerHtml()) : false;
        }
    }

    public Node clone() {
		...
	}

	...

org.jsoup.nodes.Element extends Node

org.jsoup.nodes.Document extends Element

应用场景

CASE : 解析 HTML文档 => 获得 Document 对象

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

String html = "<html><head><title>First parse</title></head><body><p>Parsed HTML into a doc.</p></body></html>";
Document doc = Jsoup.parse(html);

CASE : 解析 HTML 片段 => 获得 Document 对象

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;

String html = "<div><p>Lorem ipsum.</p>";
Document doc = Jsoup.parseBodyFragment(html);
Element body = doc.body();

CASE : 解析 URL => 获得 Document 对象

org.jsoup.Connection connection = Jsoup.connect("http://example.com/");
Document doc = connection.get();//HTTP Method = GET
String title = doc.title();

还可以携带cookie等参数:(和Python的爬虫类似)

Document doc = Jsoup.connect("http://example.com")   
.data("query", "Java")   
.userAgent("Mozilla")   
.cookie("auth", "token")   
.timeout(3000)   
.post(); //HTTP Method = POST

CASE : 解析 HTML 本地文件 => 获得 Document 对象

File input = new File("/tmp/input.html"); 
Document doc = Jsoup.parse(input, "UTF-8", "http://example.com/");


/**
 * 提取文件里面的文本信息
 */
public static String openFile(String szFileName) {
    try {
        BufferedReader bis = new BufferedReader(new InputStreamReader(new FileInputStream(new File(szFileName)), ENCODE));
        String szContent = "";
        String szTemp;

        while ((szTemp = bis.readLine()) != null) {
            szContent += szTemp + "\n";
        }
        bis.close();
        return szContent;
    } catch (Exception e) {
        return "";
    }
}

CASE : Element#hasText()/text()/ownText()/wholeText()

  • HTML 文档
<html>
<head><title>JSoup Parse Demo</title></head>
<body>
    <div id="demoDivId" style="min-height: 48px;"> hello<span>world<b>!</b></span> </div>
    <p>Parsed HTML into a doc.</p>
</body>
</html>
  • Demo Code
final static String classpath = ClassLoader.getSystemResource("").getPath();//如: /E:/source_code/xxx/xxx-bigdata/xxx-common-demo/target/classes/
final static String htmlFilePath = classpath + "sample-dataset/html/demo.html";

String htmlContent = htmlReader.readHtml( htmlFilePath );
Document document = Jsoup.parse(htmlContent);

Element element = document.body().getElementById("demoDivId");
log.info("cssSelector:{}", element.cssSelector());//cssSelector:#demoDivId
log.info( "hasText:{}" , element.hasText() ); //hasText:true
log.info( "text:{}" , element.text() );text:helloworld!
log.info( "ownText:{}" , element.ownText() ); ownText:hello
log.info( "wholeText:{}" , element.wholeText() ); wholeText: helloworld! 

CASE : Element#html()/outerHtml()

  • HTML 文档

同上一案例

  • Demo Code
...
Element element = document.body().getElementById("demoDivId");

log.info( "html(innerHtml):{}" , element.html() );
log.info( "outerHtml:\n{}" , element.outerHtml() );
  • out
html(innerHtml):hello<span>world<b>!</b></span>
outerHtml:
<div id="demoDivId" style="min-height: 48px;">
  hello<span>world<b>!</b></span> 
</div>

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

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

相关文章

top命令和系统负载

1 top中的字段说明 top是一个实时系统监视工具&#xff0c;可以动态展现出 CPU 使用率、内存使用情况、进程状态等信息&#xff0c;注意这些显示的文本不能直接使用 > 追加到文件中。 [rootvv~]# top -bn 1 | head top - 20:08:28 up 138 days, 10:29, 4 users, load av…

golang实现简单的redis服务4(实现过期时间功能)

为什么要做过期时间?redis失效时间是如何做的redis有那些过期策略,优缺点,实现原理?redis使用的什么方案 redis 有那些内存淘汰策略?常用的是什么,为什么?noeviction: 不处理lru: 未使用时间最久的keylfu: 使用次数最少的keyrandom: 随机keyvolatile与allkeys的区别 仓库地…

VMware:如何在CentOS7上开启22端口

打开虚拟机&#xff1a;【编辑】【虚拟机网络设置】 其中填入的虚拟机IP地址是虚拟机中centos的IP地址&#xff0c;虚拟机端口为需要映射的centos端口 配置好之后保存&#xff0c;打开宿主机 win cmd telnet 192.168.1.26 22 如果出现上述窗口&#xff0c;则说明已经成功开放…

项目中使用AntV L7地图(五)添加飞线

项目中使用AntV L7地图&#xff0c;添加 飞线 文档地址&#xff1a;https://l7.antv.antgroup.com/zh/examples/line/animate/#trip_animate 一、初始化地图 使用的地图文件为四川地图JSON&#xff0c;下载地址:https://datav.aliyun.com/portal/school/atlas/area_selector#&…

基于FPGA的智能电子密码指纹锁(开源全免)

基于FPGA的智能电子密码指纹锁 一、功能描述硬件资源需求 二、整体框架知识准备AS608指纹模块4*4数字键盘模块 三、Verilog代码实现以及仿真验证1.AS608_data模块2.check_hand模块3.four_four_key模块4.check_mima模块5.change_mima模块6.seg_ctrl模块7.uart_top模块8.key_debo…

【Vue2+Element-ui】el-dialog宽度适配

1、不适配问题 分辨率100%-页面 分辨率150%-页面 在项目中&#xff0c;我开发分辨率一直是100%&#xff0c;但是客户使用的分辨率不相同&#xff0c;所以宽度要适配 2、解决-封装mixins.js 1)、封装的mixins 我将宽度设置成动态的&#xff0c;因为我的项目中需求不同。 expor…

css矩形样式,两边圆形

废话不多说&#xff0c;代码如下&#xff0c;直接拷贝即可使用&#xff1a; index.vue文件 <template><view class"wrap"><view class"tabs"><view class"tab active"><view class"name">标签</view…

【OpenCV】图像阈值

简单阈值法 此方法是直截了当的。如果像素值大于阈值&#xff0c;则会被赋为一个值&#xff08;可能为白色&#xff09;&#xff0c;否则会赋为另一个值&#xff08;可能为黑色&#xff09;。使用的函数是 cv.threshold。第一个参数是源图像&#xff0c;它应该是灰度图像。第二…

使用微信小程序调用飞桨PaddleX平台自行训练的模型——微信小程序用训练的牡丹花模型Demo测试

&#x1f3bc;个人主页&#xff1a;【Y小夜】 &#x1f60e;作者简介&#xff1a;一位双非学校的大二学生&#xff0c;编程爱好者&#xff0c; 专注于基础和实战分享&#xff0c;欢迎私信咨询&#xff01; &#x1f386;入门专栏&#xff1a;&#x1f387;【MySQL&#xff0…

Wordpress设置固定链接形式后出现404错误

比如固定连接设置为 /archives/%post_id%.html 这种形式&#xff0c;看起来比较舒服。对搜索引擎也友好。 出现404需要设置伪静态

JavaWeb学习--cookie和session,实现登录的记住我和验证码功能

目录 &#xff08;一&#xff09;Cookie概述 1.什么叫Cookie 2.Cookie规范 3.Cookie的覆盖 4.cookie的最大存活时间 ​​​​​​&#xff08;Cookie的生命&#xff09; &#xff08;二&#xff09; Cookie的API 1.创建Cookie&#xff1a;new 构造方法 2.保存到客户端浏…

Linux网络测试指令

Ping Ping命令是一个网络工具&#xff0c;用于测试主机之间的可达性。它通过发送ICMP&#xff08;Internet Control Message Protocol&#xff09;回声请求消息到目标主机&#xff0c;并等待接收ICMP回声应答消息来判断目标是否可达以及测量往返时间。Ping命令对于诊断网络连接…

【伪代码】数据结构-期末复习 线性表

目录 例1 矩阵相乘 线性表 2.1 线性表的类型定义 例2-1 求并集 LALA∪LB 例2-2 有序表归并 2. 2 线性表的顺序表示和实现 1&#xff0e;构造空表 2&#xff0e;插入 3&#xff0e;删除 4&#xff0e;定位 顺序表的优点&#xff1a; 顺序表的缺点&#xff1a; 例…

<C++11> 智能指针

目录 前言 C11和boost中智能指针的关系 一、智能指针的使用及原理 1. 智能指针介绍 2. 智能指针的使用 3. 智能指针的原理 二、C中的智能指针 1. auto_ptr 2. unique_ptr 3. shared_ptr std::shared_ptr的基本设计 shared_ptr的线程安全问题 定制删除器 4. weak_ptr shared_pt…

书生实战营第四期-进阶岛第六关-MindSearch 快速部署

一、开发环境配置 1、打开codespace主页&#xff0c;选择Blank模板进行创建 Codespaces 2、创建conda环境隔离并安装依赖 conda create -n mindsearch python3.10 -y conda init 因为是新建的codespace&#xff0c;在第一次创建conda环境时&#xff0c;需要conda init 然后再…

ViT学习笔记(二) Patch+Position Embedding阶段的详细推演与理解

我认为讲得最好的一个文章&#xff1a;Vision Transformer详解-CSDN博客 有很多文章&#xff0c;自己并没有完全正确理解。 我的笔记&#xff0c;以ViT的标准应用为例&#xff1a; • 输入图像&#xff1a;输入图像的尺寸是224x224&#xff0c;且是RGB图像&#xff0c;因此输…

JS听到了强运的回响

正则表达式 介绍 正则表达式是用于匹配字符串中字符组合的模式&#xff0c;在JS中&#xff0c;正则表达式也是对象 通常用来查找&#xff0c;替换那些符合正则表达式的文本 就是筛选出符合条件的一类人 比如说 有人喜欢玩艾斯爱慕&#xff0c;那他喜欢的就是这一类人&…

工业4.0下的IT网络与OT网络

https://zhuanlan.zhihu.com/p/498984722 随着“中国制造2025”的深入推进&#xff0c;制药行业以手工为主的传统生产方式正在被以“工业4.0 ”为核心的自动化生产方式逐步替代。 为了实现生产自动化&#xff0c;很多制药企业都引入了由PLC&#xff08;可编程逻辑控制器 &am…

C# MVVM 牛牛的实现依赖注入和MVVM绑定(DependencyInjection+CommunityToolkit)

这段时间在网上发现搜索MVVM数据绑定时&#xff0c;发现很多都是最基本的数据绑定&#xff0c;完全没有考虑依赖注入的问题&#xff0c;这里实现一下我们的方法&#xff0c;让我们的数据绑定和依赖注入都变得简单起来。 安装资源包 首先我们要下载一下资源包DependencyInject…

gitee常见命令

目录 1.本地分支重命名 2.更新远程仓库分支 3.为当前分支设置远程跟踪分支 4.撤销已经push远程的代码 5.idea->gitee的‘还原提交’ 需要和本地当前的代码解决冲突 解决冲突 本地工作区的差异代码显示 本地commit和push远程 6.idea->gitee的‘将当前分支重置到此…