ElasticSearch 查询与 Java API 实践(下)

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
简介: ElasticSearch 查询与 Java API 实践

五、根据关键字分页搜索


在存在大量数据时,一般我们进行查询都需要进行分页查询。例如:我们指定页码、并指定每页显示多少条数据,然后Elasticsearch返回对应页码的数据。


1、使用from和size来进行分页


在执行查询时,可以指定from(从第几条数据开始查起)和size(每页返回多少条)数

据,就可以轻松完成分页。


l from = (page – 1) * size


POST /es_db/_doc/_search 
{ 
"from": 0, 
"size": 2, 
"query": { 
"match": { 
"address": "广州天河" 
} 
} 
} 


2、使用scroll方式进行分页


前面使用from和size方式,查询在1W-5W条数据以内都是OK的,但如果数据比较多的时候,会出现性能问题。Elasticsearch做了一个限制,不允许查询的是10000条以后的数据。如果要查询1W条以后的数据,需要使用Elasticsearch中提供的scroll游标来查询。


在进行大量分页时,每次分页都需要将要查询的数据进行重新排序,这样非常浪费性能。


使用scroll是将要用的数据一次性排序好,然后分批取出。性能要比from + size好得多。


使用scroll查询后,排序后的数据会保持一定的时间,后续的分页查询都从该快照取数据

即可。


2.1、第一次使用scroll分页查询


此处,我们让排序的数据保持1分钟,所以设置scroll为1m


GET /es_db/_search?scroll=1m 
{ 
"query": { 
"multi_match":{ 
"query":"广州长沙张三", 
"fields":["address","name"] 
} 
},
"size":100 
} 


执行后,我们注意到,在响应结果中有一项:"_scroll_id": "FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFldqc1c1Y3Y3Uzdpb3FaYTFMT094RFEAAAAAAABLkBZnY1dPTFI5SlFET1BlOUNDQ0RyZi1B" (注意,这个需要填你自己的 _scroll_id)


后续,我们需要根据这个_scroll_id来进行查询


2.2、第二次直接使用scroll id进行查询


GET _search/scroll?scroll=1m 
{ 
"scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFldqc1c1Y3Y3Uzdpb3FaYTFMT094RFEAAAAAAABLkBZnY1dPTFI5SlFET1BlOUNDQ0RyZi1B" 
} 


六、Elasticsearch SQL


image.png


Elasticsearch SQL允许执行类SQL的查询,可以使用REST接口、命令行或者是JDBC,都可以使用SQL来进行数据的检索和数据的聚合。

Elasticsearch SQL特点:


本地集成


Elasticsearch SQL是专门为Elasticsearch构建的。每个SQL查询都根据底层存储对相

关节点有效执行。


没有额外的要求


不依赖其他的硬件、进程、运行时库,Elasticsearch SQL可以直接运行在Elasticsearch集群上


轻量且高效像SQL那样简洁、高效地完成查询


1、SQL与Elasticsearch对应关系


**SQL ** **Elasticsearch **
column(列) field(字段)
row(行) document(文档)
table(表) index(索引)
schema(模式) mapping(映射)
database server(数据库服务器) Elasticsearch集群实例


2、Elasticsearch SQL语法


SELECT select_expr [, ...] 
[ FROM table_name ] 
[ WHERE condition ] 
[ GROUP BY grouping_element [, ...] ] 
[ HAVING condition] 
[ ORDER BY expression [ ASC | DESC ] [, ...] ] 
[ LIMIT [ count ] ] 
[ PIVOT ( aggregation_expr FOR column IN ( value [ [ AS ] alias ] [, ...] ) ) ] 


目前FROM只支持单表


3、职位查询案例


3.1、查询职位索引库中的一条数据


format:表示指定返回的数据类型 
//1.查询职位信息 
GET /_sql?format=txt 
{ 
"query":"SELECT * FROM es_db limit 1" 
} 
#返回数据
    address    |      age      |     name      |    remark     |      sex      
---------------+---------------+---------------+---------------+---------------
广州天河公园         |25             |张三             |java developer |1     


除了txt类型,Elasticsearch SQL还支持以下类型,


**格式 ** **描述 **
csv 逗号分隔符
json JSON格式tsv 制表符分隔符
txt 类cli表示
yaml YAML人类可读的格式


3.2、将SQL转换为DSL


GET /_sql/translate 
{ 
"query":"SELECT * FROM es_db limit 1" 
} 


结果如下:


{ 
"size" : 1, 
"_source" : { 
"includes" : [ 
"age", 
"remark", 
"sex" 
], 
"excludes" : [ ] 
}, 
"docvalue_fields" : [ 
{ 
"field" : "address" 
}, 
{ 
"field" : "book" 
}, 
{ 
"field" : "name" 
} 
], 
"sort" : [ 
{ 
"_doc" : { 
"order" : "asc" 
} 
} 
] 
}


3.4、职位全文检索


3.4.1、需求


检索address包含广州和name中包含张三的用户。


3.4.2、MATCH函数


在执行全文检索时,需要使用到MATCH函数。


MATCH( 
 field_exp, 
 constant_exp 
 [, options]) 


field_exp:匹配字段


constant_exp:匹配常量表达式


3.4.3、实现


GET /_sql?format=txt 
{ 
"query":"select * from es_db where MATCH(address, '广州') or MATCH(name, '张三') limi 
t 10" 
} 
.4、通过Elasticsearch SQL方式实现分组统计 
.4.2、基于Elasticsearch SQL方式实现 
GET /_sql?format=txt 
{ 
"query":"select age, count(*) as age_cnt from es_db group by age" 
} 


这种方式要更加直观、简洁。


Elasticsearch SQL目前的一些限制


目前Elasticsearch SQL还存在一些限制。例如:不支持JOIN、不支持较复杂的子查询。所以,有一些相对复杂一些的功能,还得借助于DSL方式来实现。


七、Java API 操作 ES


相关依赖:


<dependencies>
<!‐‐ ES的高阶的客户端API ‐‐>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch‐rest‐high‐level‐client</artifactId>
<version>7.6.1</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j‐core</artifactId>
<version>2.11.1</version>
</dependency>
<!‐‐ 阿里巴巴出品的一款将Java对象转换为JSON、将JSON转换为Java对象的库 ‐‐>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.14.3</version>
<scope>test</scope>
</dependency>
</dependencies>


使用JavaAPI来操作ES集群


**初始化连接 **


**使用的是RestHighLevelClient去连接ES集群,后续操作ES中的数据 **


public JobFullTextServiceImpl() {
  // 建立与ES的连接
  // 1. 使用RestHighLevelClient构建客户端连接。
  // 2. 基于RestClient.builder方法来构建RestClientBuilder
  // 3. 用HttpHost来添加ES的节点
  /* RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("192.168.21.130", 9200, "http")
                , new HttpHost("192.168.21.131", 9200, "http")
                , new HttpHost("192.168.21.132", 9200, "http"));
        */
  RestClientBuilder restClientBuilder = RestClient.builder(
    new HttpHost("127.0.0.1", 9200, "http"));
  restHighLevelClient = new RestHighLevelClient(restClientBuilder);
}


添加职位数据到ES中


使用IndexRequest对象来描述请求


可以设置请求的参数:设置ID、并设置传输ES的数据——注意因为ES都是使用JSON(DSL)来去操作数据的,所以需要使用一个FastJSON的库来将对象转换为JSON字符串进行操作


@Override
public void add(JobDetail jobDetail) throws IOException {
    //1.  构建IndexRequest对象,用来描述ES发起请求的数据。
    IndexRequest indexRequest = new IndexRequest(JOB_IDX);
    //2.  设置文档ID。
    indexRequest.id(jobDetail.getId() + "");
    //3.  使用FastJSON将实体类对象转换为JSON。
    String json = JSONObject.toJSONString(jobDetail);
    //4.  使用IndexRequest.source方法设置文档数据,并设置请求的数据为JSON格式。
    indexRequest.source(json, XContentType.JSON);
    //5.  使用ES High level client调用index方法发起请求,将一个文档添加到索引中。
    restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
}


查询/删除/搜索/分页


增/删/修改


@Override
public void add(JobDetail jobDetail) throws IOException {
    //1.  构建IndexRequest对象,用来描述ES发起请求的数据。
    IndexRequest indexRequest = new IndexRequest(JOB_IDX);
    //2.  设置文档ID。
    indexRequest.id(jobDetail.getId() + "");
    //3.  使用FastJSON将实体类对象转换为JSON。
    String json = JSONObject.toJSONString(jobDetail);
    //4.  使用IndexRequest.source方法设置文档数据,并设置请求的数据为JSON格式。
    indexRequest.source(json, XContentType.JSON);
    //5.  使用ES High level client调用index方法发起请求,将一个文档添加到索引中。
    restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);
}
@Override
public JobDetail findById(long id) throws IOException {
    // 1. 构建GetRequest请求。
    GetRequest getRequest = new GetRequest(JOB_IDX, id + "");
    // 2. 使用RestHighLevelClient.get发送GetRequest请求,并获取到ES服务器的响应。
    GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
    // 3. 将ES响应的数据转换为JSON字符串
    String json = getResponse.getSourceAsString();
    // 4. 并使用FastJSON将JSON字符串转换为JobDetail类对象
    JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
    // 5. 记得:单独设置ID
    jobDetail.setId(id);
    return jobDetail;
}
@Override
public void update(JobDetail jobDetail) throws IOException {
    // 1. 判断对应ID的文档是否存在
    // a) 构建GetRequest
    GetRequest getRequest = new GetRequest(JOB_IDX, jobDetail.getId() + "");
    // b) 执行client的exists方法,发起请求,判断是否存在
    boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
    if(exists) {
        // 2. 构建UpdateRequest请求
        UpdateRequest updateRequest = new UpdateRequest(JOB_IDX, jobDetail.getId() + "");
        // 3. 设置UpdateRequest的文档,并配置为JSON格式
        updateRequest.doc(JSONObject.toJSONString(jobDetail), XContentType.JSON);
        // 4. 执行client发起update请求
        restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
    }
}
@Override
public void deleteById(long id) throws IOException {
    // 1. 构建delete请求
    DeleteRequest deleteRequest = new DeleteRequest(JOB_IDX, id + "");
    // 2. 使用RestHighLevelClient执行delete请求
    restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
}


全文检索


@Override
public List<JobDetail> searchByKeywords(String keywords) throws IOException {
    // 1.构建SearchRequest检索请求
    // 专门用来进行全文检索、关键字检索的API
    SearchRequest searchRequest = new SearchRequest(JOB_IDX);
    // 2.创建一个SearchSourceBuilder专门用于构建查询条件
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    // 3.使用QueryBuilders.multiMatchQuery构建一个查询条件(搜索title、jd),并配置到SearchSourceBuilder
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "title", "jd");
    // 将查询条件设置到查询请求构建器中
    searchSourceBuilder.query(multiMatchQueryBuilder);
    // 4.调用SearchRequest.source将查询条件设置到检索请求
    searchRequest.source(searchSourceBuilder);
    // 5.执行RestHighLevelClient.search发起请求
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    SearchHit[] hitArray = searchResponse.getHits().getHits();
    // 6.遍历结果
    ArrayList<JobDetail> jobDetailArrayList = new ArrayList<>();
    for (SearchHit documentFields : hitArray) {
        // 1)获取命中的结果
        String json = documentFields.getSourceAsString();
        // 2)将JSON字符串转换为对象
        JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
        // 3)使用SearchHit.getId设置文档ID
        jobDetail.setId(Long.parseLong(documentFields.getId()));
        jobDetailArrayList.add(jobDetail);
    }
    return jobDetailArrayList;
}


分页查询


@Override
public Map<String, Object> searchByPage(String keywords, int pageNum, int pageSize) throws IOException {
    // 1.构建SearchRequest检索请求
    // 专门用来进行全文检索、关键字检索的API
    SearchRequest searchRequest = new SearchRequest(JOB_IDX);
    // 2.创建一个SearchSourceBuilder专门用于构建查询条件
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    // 3.使用QueryBuilders.multiMatchQuery构建一个查询条件(搜索title、jd),并配置到SearchSourceBuilder
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "title", "jd");
    // 将查询条件设置到查询请求构建器中
    searchSourceBuilder.query(multiMatchQueryBuilder);
    // 每页显示多少条
    searchSourceBuilder.size(pageSize);
    // 设置从第几条开始查询
    searchSourceBuilder.from((pageNum - 1) * pageSize);
    // 4.调用SearchRequest.source将查询条件设置到检索请求
    searchRequest.source(searchSourceBuilder);
    // 5.执行RestHighLevelClient.search发起请求
    SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    SearchHit[] hitArray = searchResponse.getHits().getHits();
    // 6.遍历结果
    ArrayList<JobDetail> jobDetailArrayList = new ArrayList<>();
    for (SearchHit documentFields : hitArray) {
        // 1)获取命中的结果
        String json = documentFields.getSourceAsString();
        // 2)将JSON字符串转换为对象
        JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
        // 3)使用SearchHit.getId设置文档ID
        jobDetail.setId(Long.parseLong(documentFields.getId()));
        jobDetailArrayList.add(jobDetail);
    }
    // 8. 将结果封装到Map结构中(带有分页信息)
    // a) total -> 使用SearchHits.getTotalHits().value获取到所有的记录数
    // b) content -> 当前分页中的数据
    long totalNum = searchResponse.getHits().getTotalHits().value;
    HashMap hashMap = new HashMap();
    hashMap.put("total", totalNum);
    hashMap.put("content", jobDetailArrayList);
    return hashMap;
}


使用scroll分页方式查询 (深分页)


  1. 第一次查询,不带scroll_id,所以要设置scroll超时时间


  1. 超时时间不要设置太短,否则会出现异常


  1. 第二次查询,SearchSrollRequest


@Override
public Map<String, Object> searchByScrollPage(String keywords, String scrollId, int pageSize) throws IOException {
    SearchResponse searchResponse = null;
    if(scrollId == null) {
        // 1.构建SearchRequest检索请求
        // 专门用来进行全文检索、关键字检索的API
        SearchRequest searchRequest = new SearchRequest(JOB_IDX);
        // 2.创建一个SearchSourceBuilder专门用于构建查询条件
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // 3.使用QueryBuilders.multiMatchQuery构建一个查询条件(搜索title、jd),并配置到SearchSourceBuilder
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keywords, "title", "jd");
        // 将查询条件设置到查询请求构建器中
        searchSourceBuilder.query(multiMatchQueryBuilder);
        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title");
        highlightBuilder.field("jd");
        highlightBuilder.preTags("<font color='red'>");
        highlightBuilder.postTags("</font>");
        // 给请求设置高亮
        searchSourceBuilder.highlighter(highlightBuilder);
        // 每页显示多少条
        searchSourceBuilder.size(pageSize);
        // 4.调用SearchRequest.source将查询条件设置到检索请求
        searchRequest.source(searchSourceBuilder);
        //--------------------------
        // 设置scroll查询
        //--------------------------
        searchRequest.scroll(TimeValue.timeValueMinutes(5));
        // 5.执行RestHighLevelClient.search发起请求
        searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
    }
    // 第二次查询的时候,直接通过scroll id查询数据
    else {
        SearchScrollRequest searchScrollRequest = new SearchScrollRequest(scrollId);
        searchScrollRequest.scroll(TimeValue.timeValueMinutes(5));
        // 使用RestHighLevelClient发送scroll请求
        searchResponse = restHighLevelClient.scroll(searchScrollRequest, RequestOptions.DEFAULT);
    }
    //--------------------------
    // 迭代ES响应的数据
    //--------------------------
    SearchHit[] hitArray = searchResponse.getHits().getHits();
    // 6.遍历结果
    ArrayList<JobDetail> jobDetailArrayList = new ArrayList<>();
    for (SearchHit documentFields : hitArray) {
        // 1)获取命中的结果
        String json = documentFields.getSourceAsString();
        // 2)将JSON字符串转换为对象
        JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
        // 3)使用SearchHit.getId设置文档ID
        jobDetail.setId(Long.parseLong(documentFields.getId()));
        jobDetailArrayList.add(jobDetail);
        // 设置高亮的一些文本到实体类中
        // 封装了高亮
        Map<String, HighlightField> highlightFieldMap = documentFields.getHighlightFields();
        HighlightField titleHL = highlightFieldMap.get("title");
        HighlightField jdHL = highlightFieldMap.get("jd");
        if(titleHL != null) {
            // 获取指定字段的高亮片段
            Text[] fragments = titleHL.getFragments();
            // 将这些高亮片段拼接成一个完整的高亮字段
            StringBuilder builder = new StringBuilder();
            for(Text text : fragments) {
                builder.append(text);
            }
            // 设置到实体类中
            jobDetail.setTitle(builder.toString());
        }
        if(jdHL != null) {
            // 获取指定字段的高亮片段
            Text[] fragments = jdHL.getFragments();
            // 将这些高亮片段拼接成一个完整的高亮字段
            StringBuilder builder = new StringBuilder();
            for(Text text : fragments) {
                builder.append(text);
            }
            // 设置到实体类中
            jobDetail.setJd(builder.toString());
        }
    }
    // 8. 将结果封装到Map结构中(带有分页信息)
    // a) total -> 使用SearchHits.getTotalHits().value获取到所有的记录数
    // b) content -> 当前分页中的数据
    long totalNum = searchResponse.getHits().getTotalHits().value;
    HashMap hashMap = new HashMap();
    hashMap.put("scroll_id", searchResponse.getScrollId());
    hashMap.put("content", jobDetailArrayList);
    return hashMap;
}


高亮查询


  1. 配置高亮选项


// 设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.field("jd");
highlightBuilder.preTags("<font color='red'>");
highlightBuilder.postTags("</font>");


  1. 需要将高亮的字段拼接在一起,设置到实体类中


// 1)获取命中的结果
String json = documentFields.getSourceAsString();
// 2)将JSON字符串转换为对象
JobDetail jobDetail = JSONObject.parseObject(json, JobDetail.class);
// 3)使用SearchHit.getId设置文档ID
jobDetail.setId(Long.parseLong(documentFields.getId()));
jobDetailArrayList.add(jobDetail);
// 设置高亮的一些文本到实体类中
// 封装了高亮
Map<String, HighlightField> highlightFieldMap = documentFields.getHighlightFields();
HighlightField titleHL = highlightFieldMap.get("title");
HighlightField jdHL = highlightFieldMap.get("jd");
if(titleHL != null) {
    // 获取指定字段的高亮片段
    Text[] fragments = titleHL.getFragments();
    // 将这些高亮片段拼接成一个完整的高亮字段
    StringBuilder builder = new StringBuilder();
    for(Text text : fragments) {
        builder.append(text);
    }
    // 设置到实体类中
    jobDetail.setTitle(builder.toString());
}
if(jdHL != null) {
    // 获取指定字段的高亮片段
    Text[] fragments = jdHL.getFragments();
    // 将这些高亮片段拼接成一个完整的高亮字段
    StringBuilder builder = new StringBuilder();
    for(Text text : fragments) {
        builder.append(text);
    }
    // 设置到实体类中
    jobDetail.setJd(builder.toString());
}


相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
相关文章
|
3天前
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
25 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
4天前
|
数据采集 JSON 监控
速卖通商品列表接口(以 AliExpress Affiliate 商品查询 API 为例)
以下是使用 Python 调用速卖通商品列表接口(以 AliExpress Affiliate 商品查询 API 为例)的代码示例。该示例包含准备基础参数、生成签名、发送请求和处理响应等关键步骤,并附有详细注释说明。代码展示了如何通过公共参数和业务参数构建请求,使用 HMAC-SHA256 加密生成签名,确保请求的安全性。最后,解析 JSON 响应并输出商品信息。此接口适用于商品监控、数据采集与分析及商品推荐等场景。注意需通过 OAuth2.0 获取 `access_token`,并根据官方文档调整参数和频率限制。
|
1天前
|
数据采集 JSON Java
Java爬虫获取微店快递费用item_fee API接口数据实现
本文介绍如何使用Java开发爬虫程序,通过微店API接口获取商品快递费用(item_fee)数据。主要内容包括:微店API接口的使用方法、Java爬虫技术背景、需求分析和技术选型。具体实现步骤为:发送HTTP请求获取数据、解析JSON格式的响应并提取快递费用信息,最后将结果存储到本地文件中。文中还提供了完整的代码示例,并提醒开发者注意授权令牌、接口频率限制及数据合法性等问题。
|
1天前
|
数据采集 存储 Java
Java爬虫获取微店店铺所有商品API接口设计与实现
本文介绍如何使用Java设计并实现一个爬虫程序,以获取微店店铺的所有商品信息。通过HttpClient发送HTTP请求,Jsoup解析HTML页面,提取商品名称、价格、图片链接等数据,并将其存储到本地文件或数据库中。文中详细描述了爬虫的设计思路、代码实现及注意事项,包括反爬虫机制、数据合法性和性能优化。此方法可帮助商家了解竞争对手,为消费者提供更全面的商品比较。
|
23天前
|
算法 Java 程序员
菜鸟之路Day06一一Java常用API
《菜鸟之路Day06——Java常用API》由blue编写,发布于2025年1月24日。本文详细介绍了Java中常用的API,包括JDK7的时间类(Date、SimpleDateFormat、Calendar)和JDK8新增的时间API(ZoneId、Instant、DateTimeFormatter等),以及包装类的使用。通过多个实例练习,如时间计算、字符串转整数、十进制转二进制等,帮助读者巩固所学内容,提升编程技能。文章强调了理论与实践结合的重要性,鼓励读者多做练习以提高学习效率。
76 28
|
5天前
|
缓存 Java 应用服务中间件
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
java语言后台管理若依框架-登录提示404-接口异常-系统接口404异常如何处理-登录验证码不显示prod-api/captchaImage 404 (Not Found) 如何处理-解决方案优雅草卓伊凡
30 5
|
21天前
|
监控 Cloud Native 安全
基于 API 网关践行 API First 开发实践
API First 开发模式的核心在于:以 API 为先,将其视为“头等公民”,在构建应用、服务及集成之前,应优先定义并设计 API 及其配套。API First 作为一种相对较新的开发模式,它已逐渐流行并获得业内的广泛认可。
|
1月前
|
JSON Java 数据挖掘
利用 Java 代码获取淘宝关键字 API 接口
在数字化商业时代,精准把握市场动态与消费者需求是企业成功的关键。淘宝作为中国最大的电商平台之一,其海量数据中蕴含丰富的商业洞察。本文介绍如何通过Java代码高效、合规地获取淘宝关键字API接口数据,帮助商家优化产品布局、制定营销策略。主要内容包括: 1. **淘宝关键字API的价值**:洞察用户需求、优化产品标题与详情、制定营销策略。 2. **获取API接口的步骤**:注册账号、申请权限、搭建Java开发环境、编写调用代码、解析响应数据。 3. **注意事项**:遵守法律法规与平台规则,处理API调用限制。 通过这些步骤,商家可以在激烈的市场竞争中脱颖而出。
|
2月前
|
存储 API 计算机视觉
自学记录HarmonyOS Next Image API 13:图像处理与传输的开发实践
在完成数字版权管理(DRM)项目后,我决定挑战HarmonyOS Next的图像处理功能,学习Image API和SendableImage API。这两个API支持图像加载、编辑、存储及跨设备发送共享。我计划开发一个简单的图像编辑与发送工具,实现图像裁剪、缩放及跨设备共享功能。通过研究,我深刻体会到HarmonyOS的强大设计,未来这些功能可应用于照片编辑、媒体共享等场景。如果你对图像处理感兴趣,不妨一起探索更多高级特性,共同进步。
89 11
|
2月前
|
人工智能 数据可视化 API
自学记录鸿蒙API 13:Calendar Kit日历功能从学习到实践
本文介绍了使用HarmonyOS的Calendar Kit开发日程管理应用的过程。通过API 13版本,不仅实现了创建、查询、更新和删除日程等基础功能,还深入探索了权限请求、日历配置、事件添加及查询筛选等功能。实战项目中,开发了一个智能日程管理工具,具备可视化管理、模糊查询和智能提醒等特性。最终,作者总结了模块化开发的优势,并展望了未来加入语音助手和AI推荐功能的计划。
171 1