前言
??GraphQL 是一種用于 API 的查詢語言,是由 Facebook 開源的一種用于提供數據查詢服務的抽象框架。在服務端 API 開發中,很多時候定義一個接口返回的數據相對固定,因此要獲得更多信息或者只想得到某部分信息時,基于 RESTful API 的接口就顯得不那么靈活。而 GraphQL 對 API 中的數據提供了一套易于理解的完整描述,使得客戶端能夠準確地獲得它需要的數據,而且沒有任何冗余,也讓 API 更容易地隨著時間推移而演進,還能用于構建強大的開發者工具。 ??目前,LeetCode 和 GitHub 都借助 GraphQL 來設計,提供了更大的靈活性,對于想借助 GitHub 來了解 GraphQL 可直接訪問 GraphQL API v4 ,或者參考 GraphQL 實戰:Github V4 API使用。而對于在 LeetCode 上使用 GraphQL 查詢,相對資料少一些,因此在這,我主要以 LeetCode 為例,來做講解(其實是因為自己業余刷題時突發奇想,想寫一個爬蟲。
過程
??如果直接搜索以 Java 語言為載體的 GraphQL 的話,一大部分搜索結果都是介紹使用 graphql-java 來搭建查詢服務,而我們的目的是利用 GraphQL 來獲取想要的數據,并非自己搭建一個查詢服務,因此如果一開始就選錯了工具,就會導致后面的方向都是錯誤的。 ??以 LeetCode 第一題 1.Two Sum 為例,獲取其后端發送過來的數據。利用 F12 功能調出如下界面,選 Network
query
的字段,這是我們要構造的 GraphQL Query 的一個重要信息。 query
的字段相仿(因為有一點需要更改的細節) 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());}
}
復制代碼
執行結果: