耶拿天气数据集_耶拿简介

本文介绍了HP Labs的开源Jena Semantic Web Framework,展示了如何创建、填充RDF模型,如何使用RDQL查询语言进行查询,并演示了Jena的推理功能。文章通过创建虚构家庭的RDF模型和查询示例,解释了如何使用Jena的API处理RDF模型,并介绍了如何导入和持久化模型,以及如何利用OWL本体进行推断。
摘要由CSDN通过智能技术生成

耶拿天气数据集

资源描述框架(RDF)最近成为W3C的推荐,与XML和SOAP等其他Web标准一起被取代。 RDF可以应用于处理临时传入数据的领域(例如CRM),并且已经广泛用于社交网络和LiveJournal和TypePad等自发布软件。

Java程序员将具有使用RDF模型的技能,从而逐渐受益。 在本文中,我将带您了解HP Labs的开源Jena Semantic Web Framework的一些功能(请参阅参考资料 )。 您将学习如何创建和填充RDF模型,如何将其持久化到数据库中以及如何使用RDQL查询语言以编程方式查询它们。 最后,我将演示如何使用Jena的推理功能从本体论中推断有关模型的知识。

本文假定您对RDF有所了解-包括图形,三元组和模式之类的概念-以及Java编程的基本知识。

创建一个简单的RDF模型

让我们从基础开始:从头开始创建模型并向其中添加RDF语句。 在本节中,我将展示如何创建一个模型来描述一组虚构的家庭成员之间的关系,如图1所示:

图1.虚构的家谱
小家谱

你会描述使用性质不同的关系类型siblingOfspouseOfparentOfchildOf ,从“关系”词汇拍摄(见相关主题 )。 为简单起见,使用来自虚构名称空间http://family/ URI标识家庭成员。 词汇URI在Jena代码中经常使用,因此将它们声明为Java常量很有用,从而减少了混淆它们的风险。

耶拿的ModelFactory类是创建不同类型模型的首选方法。 在这种情况下,您需要一个空的内存模型,因此ModelFactory.createDefaultModel()是要调用的方法。 此方法返回Model的实例,您将使用该实例创建代表家庭中每个人的Resource 。 创建资源后,可以对它们进行声明并添加模型。

在耶拿(Jena)中,语句的主题始终是Resource ,谓词由Property表示,而对象是另一个Resource或文字值。 文字在耶拿用Literal类型表示。 所有这些类型共享一个公共接口RDFNode 。 您将需要四个不同的Property实例来表示家族树中的关系。 这些实例是使用Model.createProperty()创建的。

向模型添加语句的最简单方法是调用Resource.addProperty() 。 此方法在模型中创建一个以“ Resource为主题的语句。 该方法有两个参数,一个表示语句谓词的Property和该语句的对象。 addProperty()方法已重载:一个重载将RDFNode作为对象,因此可以使用ResourceLiteral 。 还有一些方便重载,它们采用Java原语或String表示的文字。 在该示例中,语句的对象是Resource代表其他家庭成员。

通过调用带有三元组的主题,谓词和对象的Model.createStatement() ,也可以在模型上直接创建语句。 请注意,以这种方式创建一个Statement不会将其添加到模型中。 如果要将其添加到模型中,请使用创建的Statement调用Model.add() ,如清单1所示:

清单1.创建一个代表虚构家庭的模型
// URI declarations
String familyUri = "http://family/";
String relationshipUri = "http://purl.org/vocab/relationship/";

// Create an empty Model
Model model = ModelFactory.createDefaultModel();

// Create a Resource for each family member, identified by their URI
Resource adam = model.createResource(familyUri+"adam");
Resource beth = model.createResource(familyUri+"beth");
Resource chuck = model.createResource(familyUri+"chuck");
Resource dotty = model.createResource(familyUri+"dotty");
// and so on for other family members

// Create properties for the different types of relationship to represent
Property childOf = model.createProperty(relationshipUri,"childOf");
Property parentOf = model.createProperty(relationshipUri,"parentOf");
Property siblingOf = model.createProperty(relationshipUri,"siblingOf");
Property spouseOf = model.createProperty(relationshipUri,"spouseOf");

// Add properties to adam describing relationships to other family members
adam.addProperty(siblingOf,beth);
adam.addProperty(spouseOf,dotty);
adam.addProperty(parentOf,edward);

// Can also create statements directly . . .
Statement statement = model.createStatement(adam,parentOf,fran);

// but remember to add the created statement to the model
model.add(statement);

完整的代码示例FamilyModel.java还演示了如何将批处理语句立即作为数组或java.util.List添加到模型java.util.List

建立家庭模型后,让我们看看如何使用Jena的查询API从信息中提取信息。

询问RDF模型

以编程方式询问Jena模型主要是通过ModelResource接口上的list()方法执行的。 这些方法可用于获取与某些条件匹配的主题,对象和Statement 。 它们还返回java.util.Iterator ,它具有返回特定对象类型的额外方法。

让我们回到清单1的家庭模型示例,看看可以如何查询它,如清单2所示:

清单2.查询族模型
// List everyone in the model who has a child:
ResIterator parents = model.listSubjectsWithProperty(parentOf);

// Because subjects of statements are Resources, the method returned a ResIterator
while (parents.hasNext()) {

  // ResIterator has a typed nextResource() method
  Resource person = parents.nextResource();

  // Print the URI of the resource
  System.out.println(person.getURI());
}

// Can also find all the parents by getting the objects of all "childOf" statements
// Objects of statements could be Resources or literals, so the Iterator returned
// contains RDFNodes
NodeIterator moreParents = model.listObjectsOfProperty(childOf);

// To find all the siblings of a specific person, the model itself can be queried 
NodeIterator siblings = model.listObjectsOfProperty(edward, siblingOf);
  
// But it's more elegant to ask the Resource directly
// This method yields an iterator over Statements
StmtIterator moreSiblings = edward.listProperties(siblingOf);

最通用的查询方法是Model.listStatements(Resource s, Property p, RDFNode o) ,是在此演示的便捷方法的基础。 这些参数中的任何一个都可以保留为null ,在这种情况下,它们可以用作通配符,匹配任何内容。 清单3显示了一些Model.listStatements()用法的示例:

清单3.使用选择器查询模型
// Find the exact statement "adam is a spouse of dotty"
model.listStatements(adam,spouseOf,dotty);
	
// Find all statements with adam as the subject and dotty as the object
model.listStatements(adam,null,dotty);
	
// Find any statements made about adam
model.listStatements(adam,null,null);

// Find any statement with the siblingOf property
model.listStatements(null,siblingOf,null);

导入和保留模型

并非所有应用程序都将以空模型开头。 更常见的是,在启动时会从现有数据中填充模型。 在这种情况下使用内存模型的缺点是,每次启动应用程序时,都必须从头开始重新填充模型。 此外,每次关闭应用程序时,对内存模型所做的任何更改都将丢失。

一种解决方案是使用Model.write()将模型序列化到文件系统,并使用Model.read()在启动时反序列化它。 但是,Jena还提供了持久化模型,这些模型被连续透明地持久化到后备存储中。 Jena可以将其模型持久保存在文件系统或关系数据库中。 当前支持的数据库引擎是PostgreSQL,Oracle和MySQL。

为了演示如何导入和持久化模型,我将以WordNet 1.6数据库的RDF表示形式导入MySQL。 因为我使用的WordNet表示形式采用几个单独的RDF文档的形式,所以将它们导入到单个Jena模型中会合并它们的语句。 图2展示了将名词和词汇表模型合并在一起后,WordNet模型的片段结构:

图2.合并的WordNet名词和词汇表模型的结构
该图说明了WordNet模型的一部分中的语句

创建数据库支持的模型的第一步是实例化MySQL驱动程序类,并创建一个DBConnection实例。 DBConnection构造函数使用用户的ID和密码来登录数据库。 它还带有一个数据库URL参数,该参数包含Jena要使用的MySQL数据库的名称,格式为"jdbc:mysql://localhost/dbname" 。 Jena可以在一个数据库中创建多个模型。 最终的DBConnection参数是数据库类型,对于MySQL来说是"MySQL"

然后,可以将DBConnection实例与Jena的ModelFactory一起使用,以创建数据库支持的模型。

一旦创建了模型,就可以从文件系统中读取WordNet RDF文档。 各种Model.read()方法可以从ReaderInputStreamURL填充模型。 可以从Notation3,N-Triples或默认情况下从RDF / XML语法解析模型。 WordNet模型已序列化为RDF / XML,因此您无需指定语法。 读取模型时,可以提供基本URI。 基本URI用于将模型中的任何相对URI转换为绝对URI。 由于WordNet文档不包含任何相对URI,因此可以将此参数指定为null

清单4显示了将WordNet RDF / XML文件导入到MySQL持久模型中的完整过程:

清单4.导入和保留WordNet模型
// Instantiate the MySQL driver
Class.forName("com.mysql.jdbc.Driver");

// Create a database connection object
DBConnection connection = new DBConnection(DB_URL, DB_USER, DB_PASSWORD, DB_TYPE);
	
// Get a ModelMaker for database-backed models
ModelMaker maker = ModelFactory.createModelRDBMaker(connection);

// Create a new model named "wordnet." Setting the second parameter to "true" causes an
// AlreadyExistsException to be thrown if the db already has a model with this name
Model wordnetModel = maker.createModel("wordnet",true);

// Start a database transaction. Without one, each statement will be auto-committed
// as it is added, which slows down the model import significantly. 
model.begin();

// For each wordnet model . . .
InputStream in = this.getClass().getClassLoader().getResourceAsStream(filename);
model.read(in,null);

// Commit the database transaction
model.commit();

现在已经填充了wordnet模型,您可以稍后通过调用ModelMaker.openModel("wordnet",true);来访问它ModelMaker.openModel("wordnet",true);

仅使用Jena的API来查询与WordNet一样大和丰富的模型将是限制性的,因为要执行的每种查询类型都需要编写几行定制代码。 幸运的是,Jena提供了一种以RDQL形式表达通用查询的机制。

RDF数据查询语言(RDQL)

RDQL是RDF的查询语言。 尽管尚未成为正式标准,但RDQL已由RDF框架广泛实施。 RDQL允许查询引擎执行访问数据模型的艰苦工作,从而简洁地表达复杂的查询。 RDQL的语法从表面上类似于SQL的语法,实际上,使用关系数据库查询的任何人都会熟悉它的某些概念。 可以在Jena网站上找到出色的RDQL教程,但是一些简短的示例对说明基础知识大有帮助。

可以使用jena.rdfquery工具针对Jena模型在命令行上执行RDQL查询。 RDFQuery从文本文件获取RDQL查询,并针对指定的模型运行它。 要针对数据库支持的模型运行,需要几个参数。 清单5显示了运行以下示例所需的完整命令行:

清单5.从命令行运行RDQL查询
$java jena.rdfquery --data jdbc:mysql://localhost/jena --user dbuser --password dbpass 
--driver com.mysql.jdbc.Driver --dbType MySQL --dbName wordnet --query example_query.rdql

如您所见,大多数这些参数提供了创建与MySQL的连接所需的详细信息。 重要的部分是--query example_query.rdql ,它是RDQL文件的位置。 还要注意,运行jena.rdfquery需要Jena的lib目录中的所有JAR文件。

清单6显示了您将检查的第一个查询:

清单6. RDQL查询以查找“本地狗”的WordNet词汇表条目
SELECT
    ?definition

WHERE
    (?concept, <wn:wordForm>, "domestic dog"),
    (?concept, <wn:glossaryEntry>, ?definition)

USING
    wn FOR <http://www.cogsci.princeton.edu/~wn/schema/>

SELECT部分声明要由查询输出的变量-在本例中为名为definition的变量。 WHERE子句引入了第二个变量concept ,并定义了与图匹配的三元组。 该查询在图中找到WHERE子句中所有三元组均成立的语句。 因此,用英语来说, WHERE子句类似于“找到带有“家犬”作为词形的概念,并找到这些概念的词汇表条目”之类的东西,如图3所示USING子句是一种便利,用于声明命名空间的前缀。

图3.与清单6中的WHERE子句匹配的图
匹配狗的词汇表条目的图

运行查询结果为:

definition
===============================================================================

"a member of the genus Canis (probably descended from the common wolf) that has
been domesticated by man since prehistoric times; occurs in many breeds; "the 
dog barked all night""

因此,在这种情况下只有一个结果。 清单7中显示的下一个查询说:“查找以单词“ bear”代表的概念,并找到这些概念的词汇表条目。

清单7. RDQL查询以查找“ bear”的WordNet词汇表条目
SELECT
    ?definition

WHERE
    (?concept, <wn:wordForm>, "bear"),
    (?concept, <wn:glossaryEntry>, ?definition)

USING
    wn FOR <http://www.cogsci.princeton.edu/~wn/schema/>

该查询返回15个结果,因为此字形代表几个不同的概念。 结果开始:

definition
===============================================================================
"massive plantigrade carnivorous or omnivorous mammals with long shaggy coats 
and strong claws"
"an investor with a pessimistic market outlook"
"have on one's person; "He wore a red ribbon"; "bear a scar""
"give birth (to a newborn); "My wife had twins yesterday!""

清单8中显示了一个更复杂的示例,它找到另外两个示例的上位词(父词):

清单8. RDQL查询以找到“ panther”和“ tiger”的WordNet上位词
SELECT
      ?wordform, ?definition

WHERE
      (?firstconcept, <wn:wordForm>, "panther"),
      (?secondconcept, <wn:wordForm>, "tiger"),

      (?firstconcept, <wn:hyponymOf>, ?hypernym),
      (?secondconcept, <wn:hyponymOf>, ?hypernym),

      (?hypernym, <wn:wordForm>, ?wordform),
      (?hypernym, <wn:glossaryEntry>, ?definition)

USING
      wn FOR <http://www.cogsci.princeton.edu/~wn/schema/>

在这里,查询显示为“找到单词'panther'和'tiger'所指的概念,找到第三个概念,其中前两个是下义词,并找到该概念的可能单词和词汇表条目”,如图所示在图4中:

图4.清单8中的WHERE子句匹配的图
图匹配豹和虎的上影

SELECT子句中都声明了wordformdefinition ,因此都将其输出。 尽管此查询仅匹配单个WordNet概念,但查询的图形可以两种方式匹配,因为该概念具有两种不同的字形:

wordform  | definition
=====================================================================================
"big cat" | "any of several large cats typically able to roar and living in the wild"
"cat"     | "any of several large cats typically able to roar and living in the wild"

在耶拿使用RDQL

Jena的com.hp.hpl.jena.rdql软件包包含在Java代码中使用RDQL所需的所有类和接口。 要创建RDQL查询,请将RDQL放入String ,然后将其传递给Query的构造函数。 通常,除非在RDQL本身中使用FROM子句另外指定,否则显式设置模型以用作查询源。 准备好QueryQueryEngine可以从中创建一个QueryEngine并执行查询。 清单9演示了此过程:

清单9.创建和运行RDQL查询
// Create a new query passing a String containing the RDQL to execute
Query query = new Query(queryString);

// Set the model to run the query against
query.setSource(model);
	
// Use the query to create a query engine
QueryEngine qe = new QueryEngine(query);

// Use the query engine to execute the query
QueryResults results = qe.exec();

Query一起使用的一种有用技术是在执行之前将其某些变量设置为固定值。 此用法模式类似于javax.sql.PreparedStatement用法。 变量通过ResultBinding对象绑定到值,该对象在执行时传递给QueryEngine 。 可以将变量绑定到Jena Resource或文字值。 在将文字绑定到变量之前,将其包装为对Model.createLiteral的调用。 清单10说明了预绑定方法:

清单10.将查询变量绑定到值
// Create a query that has variables x and y
Query query = new Query(queryString);

// A ResultBinding specifies mappings between query variables and values
ResultBinding initialBinding = new ResultBinding() ;

// Bind the query's first variable to a resource
Resource someResource = getSomeResource();
initialBinding.add("x", someResource);

// Bind the query's second variable to a literal value
RDFNode foo = model.createLiteral("bar");
initialBinding.add("y", foo);

// Execute the query with the specified values for x and y
QueryEngine qe = new QueryEngine(query);
QueryResults results = qe.exec(initialBinding);

QueryEngine.exec()返回的QueryResults对象实现java.util.Iterator 。 它的next()方法返回ResultBinding对象。 可以从ResultBinding按名称获取查询中使用的所有变量,无论它们是否是SELECT子句的一部分。 清单11显示了如何执行此操作,再次使用清单6中的RDQL查询:

清单11. RDQL查询以查找“本地狗”的WordNet词汇表条目
SELECT 
    ?definition 
WHERE 
    (?concept, <wn:wordForm>, "domestic dog"), 
    (?concept, <wn:glossaryEntry>, ?definition) 
USING 
    wn FOR <http://www.cogsci.princeton.edu/~wn/schema/>";

通过运行此查询获得的ResultBinding如预期的那样包含该单词的文字词汇表条目。 另外,您可以访问变量concept 。 通过调用ResultBinding.get()按名称获取变量。 此方法返回的所有变量都可以RDFNodeRDFNode ,如果要将它们重新绑定到另一个RDQL查询中,这将非常有用。

在这种情况下, concept变量表示RDF资源,因此从ResultBinding.get()获得的Object可以ResultBinding.get()Resource 。 然后可以调用Resource的查询方法以进一步探索模型的这一部分,如清单12所示:

清单12.处理查询结果
// Execute a query
QueryResults results = qe.exec();

// Loop over the results
while (results.hasNext()) {
  ResultBinding binding = (ResultBinding)results.next();
  
  // Print the literal value of the "definition" variable
  RDFNode definition = (RDFNode) binding.get("definition");
  System.out.println(definition.toString());

  // Get the RDF resource used in the query
  Resource concept = (Resource)binding.get("concept");

  // Query the concept directly to find other wordforms it has
  List wordforms = concept.listObjectsOfProperty(wordForm);

}

FindHypernym.java包含在源文件下载(请参阅该程序相关信息 ),总结你在这里看到的区域。 它使用清单13中所示的查询查找命令行中给出的单词的上位词:

清单13. RDQL查询以查找概念的上位词的字形和词汇表条目
SELECT 
    ?hypernym, ?definition
WHERE 
    (?firstconcept, <wn:wordForm>, ?hyponym),
    (?firstconcept, <wn:hyponymOf>, ?secondconcept),
    (?secondconcept, <wn:wordForm>, ?hypernym), 
    (?secondconcept, <wn:glossaryEntry>, ?definition)
USING 
    wn FOR <http://www.cogsci.princeton.edu/~wn/schema/>

命令行上给定的单词与下hyponym词绑定,查询会找到该词代表的概念,找到第一个概念为下义词的第二个概念,然后输出该概念的字形和定义。 清单14显示了它的输出:

清单14.运行示例FindHypernym程序
$ java FindHypernym "wisteria"

Hypernyms found for 'wisteria':

vine:   weak-stemmed plant that derives support from climbing, twining, 
or creeping along a surface

用OWL添加含义

您可能想知道为什么搜索“紫藤”的上位词只会返回其直接上位词“藤”。 如果您植物学上的想法,您可能还希望“微量营养体”显示为上调,当然还有“植物”。 确实,WordNet模型说“紫藤”是“藤”的下义词,“藤”是“微量营养体”的下义词。 凭直觉,您知道“紫藤”因此是“示营养体”的下义词,因为您知道“关系的别名”是可传递的 。 因此,您需要一种将这些知识整合到FindHypernym程序中的方法,这是OWL的所在。

Web本体语言或OWL是W3C建议书,旨在“明确表示词汇中术语的含义以及这些术语之间的关系”。 OWL与RDF Schema一起提供了一种正式描述RDF模型内容的机制。 除了定义资源可以属于的分层类之外,OWL还允许表达资源属性的特征。 例如,在所使用的关系词汇清单1 ,OWL可以用于状态下childOf属性是的逆parentOf属性。 另一个示例是声明WordNet词汇表的hyponymOf属性是可传递的。

在耶拿(Jena)中,本体被视为一种特殊的RDF模型OntModel 。 该接口允许使用编程方法来操纵本体,并使用方便的方法来创建类,属性限制等。 另一种方法是将本体视为常规RDF模型,并简单地添加定义其语义规则的语句。 清单15中演示了这两种技术。注意,还可以向现有数据模型中添加本体声明,或者使用Model.union()将本体模型与数据模型合并。

清单15.为WordNet创建OWL本体模型
// Make a new model to act as an OWL ontology for WordNet
OntModel wnOntology = ModelFactory.createOntologyModel();

// Use OntModel's convenience method to describe 
// WordNet's hyponymOf property as transitive
wnOntology.createTransitiveProperty(WordnetVocab.hyponymOf.getURI());

// Alternatively, just add a statement to the underlying model to express that
// hyponymOf is of type TransitiveProperty
wnOntology.add(WordnetVocab.hyponymOf, RDF.type, OWL.TransitiveProperty);

与耶拿的推论

给定一个本体和一个模型,Jena的推理引擎可以导出该模型未明确表达的其他语句。 耶拿(Jena)提供了几种Reasoner类型,以与不同类型的本体一起使用。 因为您要在WordNet模型中使用OWL本体,所以需要OWLReasoner

下面的示例显示如何将OWL WordNet本体应用于WordNet模型本身以创建推理模型。 我实际上将在这里使用WordNet模型的子集,仅包含下义词层次结构中“植物生命”下的那些名词。 仅使用子集的原因是,推理模型需要保存在内存中,而WordNet模型太大,无法使用内存模型。 我用来提取从全共发现模型植物模型的代码包含在本文的源代码,并命名为ExtractPlants.java(参见相关主题 )。

首先,我将从ReasonerRegistry获得一个OWLReasonerReasonerRegistry.getOWLReasoner()以其标准配置返回OWL推理程序,对于这种简单情况而言,这是很好的。 下一步是将推理机绑定到WordNet本体。 此操作将返回准备应用本体规则的推理机。 接下来,我将使用绑定推理InfModel从WordNet模型创建InfModel

从原始数据和OWL本体创建推理模型后,就可以像对待其他任何Model实例一样对待它。 因此,如清单16所示,可以将FindHypernym.java与常规Jena模型一起使用的Java代码和RDQL查询重新应用于推理模型,而无需进行任何更改:

清单16.创建和查询推理模型
// Get a reference to the WordNet plants model
ModelMaker maker = ModelFactory.createModelRDBMaker(connection);
Model model = maker.openModel("wordnet-plants",true);

// Create an OWL reasoner 
Reasoner owlReasoner = ReasonerRegistry.getOWLReasoner();

// Bind the reasoner to the WordNet ontology model
Reasoner wnReasoner = owlReasoner.bindSchema(wnOntology);

// Use the reasoner to create an inference model
InfModel infModel = ModelFactory.createInfModel(wnReasoner, model);

// Set the inference model as the source of the query
query.setSource(infModel);

// Execute the query as normal
QueryEngine qe = new QueryEngine(query);
QueryResults results = qe.exec(initialBinding);

完整的清单可在文章源中找到,名为FindInferredHypernyms.java。 清单17显示了在查询模型中查询“紫藤”的上位词时发生的情况:

清单17.运行示例FindInferredHypernyms程序
$ java FindInferredHypernyms wisteria

Hypernyms found for 'wisteria':

vine:   weak-stemmed plant that derives support from climbing, twining, or creeping along a surface
tracheophyte:   green plant having a vascular system: ferns, gymnosperms, angiosperms
vascular plant: green plant having a vascular system: ferns, gymnosperms, angiosperms
plant life:     a living organism lacking the power of locomotion
flora:  a living organism lacking the power of locomotion
plant:  a living organism lacking the power of locomotion

OWL本体中包含的信息使Jena可以推断出“紫藤”在整个模型中都有上位词。

摘要

本文展示了Jena Semantic Web Toolkit的一些最重要的功能,并通过示例展示了如何创建,导入和保留RDF模型。 您还研究了查询模型的不同方法,并了解了如何使用RDQL简洁表达任意查询。 此外,您已经了解了如何使用Jena的推理引擎对基于本体的模型进行推理。

本文中的示例演示了将数据表示为RDF模型的某些功能,以及RDQL从中提取数据的灵活性。 在您自己的Java应用程序中使用RDF模型时,此处说明的基本方法将是一个有用的起点。

Jena是一个全面的RDF工具集,其功能超出了您在此处学到的知识。 耶拿项目的主页是开始学习更多有关其功能的好地方。


翻译自: https://www.ibm.com/developerworks/xml/library/j-jena/index.html

耶拿天气数据集

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值