前言
GraphQL http://graphql.cn/ 是一种用于 API 的查询语言, 是由 Facebook 开源的一种用于提供数据查询服务的抽象框架. 在服务端 API 开发中, 很多时候定义一个接口返回的数据相对固定, 因此要获得更多信息或者只想得到某部分信息时, 基于 RESTful API 的接口就显得不那么灵活. 而 GraphQL 对 API 中的数据提供了一套易于理解的完整描述, 使得客户端能够准确地获得它需要的数据, 而且没有任何冗余, 也让 API 更容易地随着时间推移而演进, 还能用于构建强大的开发者工具.
目前, LeetCode 和 GitHub 都借助 GraphQL 来设计, 提供了更大的灵活性, 对于想借助 GitHub 来了解 GraphQL 可直接访问 GraphQL API v4 https://developer.github.com/v4/ , 或者参考 GraphQL 实战: Github V4 API 使用 https://www.jianshu.com/p/af7ac20f2c64 . 而对于在 LeetCode 上使用 GraphQL 查询, 相对资料少一些, 因此在这, 我主要以 LeetCode 为例, 来做讲解 (其实是因为自己业余刷题时突发奇想, 想写一个爬虫.
过程
如果直接搜索以 Java 语言为载体的 GraphQL 的话, 一大部分搜索结果都是介绍使用 https://github.com/graphql-java/graphql-java 来搭建查询服务, 而我们的目的是利用 GraphQL 来获取想要的数据, 并非自己搭建一个查询服务, 因此如果一开始就选错了工具, 就会导致后面的方向都是错误的.
以 LeetCode 第一题 1.Two Sum https://leetcode.com/problems/two-sum/description/ 为例, 获取其后端发送过来的数据. 利用 F12 功能调出如下界面, 选 Network
找到 graphql 文件 (有好多 graphql 文件, 可以依次点击查找自己想要的那个, 这里找到包含有题目信息的), 从 preview 中我们可以看到 data 返回了题目相关的信息
那么, 如何构造 GraphQL Query 来获取信息呢? 从 Header 中的 Request Payload 中我们可以看到一个 query 的字段, 这是我们要构造的 GraphQL Query 的一个重要信息.
我们并不一开始就用代码来获取题目信息, 而是先利用 Postman 来看看如何获取题目信息. 右键 Network 下的 graphql 文件 ->Copy->Copy as cURL(bash), 如下图所示:
之后, 打开 Postman-> 左上角 Import->Paste Raw Text 粘贴, 从 Body 中可以看到, 构造好了的 GraphQL Query 与我们在 Request Payload 中看到的 query 的字段相仿 (因为有一点需要更改的细节)
当然, 如果不想直接粘贴复制的 cURL, 那么我们可以自己在 Postman 中写 Header 和 Body, 需要注意的是这边的 Content-Type 是
application/graphql
,Body 中的 GraphQL 构造, 参照 Request Payload 中的 query 的字段来构造
获取到的结果如下:
我们在实际中, 可能并不需要提供的所有信息, 只想要某一部分, 那么只需更改 query 即可, 这也是 GraphQL 的强大之处. 比如我们只想要题目的 content 信息, 那么其 query 则为
query{question(titleSlug:"two-sum") {content}}
代码
在上边, 已经利用 Postman 查询到想要的数据了, 而现在我们要做的就是用代码将上述操作展示出来. 这边, 使用 OkHttp 来进行题目信息获取.
- import okhttp3.*;
- import org.jsoup.Connection;
- import org.jsoup.Jsoup;
- import java.io.IOException;
- import java.util.Map;
- import static java.lang.System.out;
- public class Question {
- public static void main(String... args) throws IOException {
- String questionUrl = "https://leetcode.com/problems/two-sum/description/";
- String graphqlUrl = "https://leetcode.com/graphql";
- Connection.Response response = Jsoup.connect(questionUrl)
- .method(Connection.Method.GET)
- .execute();
- Map<String,String>cookies = response.cookies();
- for (Map.Entry<String,String>entry:cookies.entrySet()){
- //out.println(entry.getKey() + ":" + entry.getValue());
- }
- String csrftoken = response.cookie("csrftoken");
- String __cfduid = response.cookie("__cfduid");
- OkHttpClient client = new OkHttpClient.Builder()
- .followRedirects(false)
- .followSslRedirects(false)
- .build();
- String postBody = "query{\n" +
- "question(titleSlug:\"two-sum\") {\n" +
- "content\n" +
- "}\n" +
- "}\n";
- Request request = new Request.Builder()
- .addHeader("Content-Type","application/graphql")
- .addHeader("Referer",questionUrl)
- .addHeader("Cookie","__cfduid=" + __cfduid + ";" + "csrftoken=" + csrftoken)
- .addHeader("x-csrftoken",csrftoken)
- .url(graphqlUrl)
- .post(RequestBody.create(MediaType.parse("application/graphql; charset=utf-8"),postBody))
- .build();
- Response response1 = client.newCall(request).execute();
- //out.println(response1.headers());
- out.println(response1.body().string());
- }
- }
执行结果:
来源: https://www.cnblogs.com/ZhaoxiCheung/p/9333476.html