1. 程式人生 > >以LeetCode為例重慶幸運農場——如何發送GraphQL Query獲取數據

以LeetCode為例重慶幸運農場——如何發送GraphQL Query獲取數據

-s 突發奇想 map.entry coo app exceptio 獲取 客戶端 包含

前言
GraphQL 是一種用於 API 的查詢語言重慶幸運農場QQ2952777280【話仙源碼論壇】hxforum.com【木瓜源碼論壇】papayabbs.com ,是由 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

找到 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());

}

}
執行結果:

┆ 涼 ┆ 暖 ┆ 降 ┆ 等 ┆ 幸 ┆ 我 ┆ 我 ┆ 裏 ┆ 將 ┆   ┆ 可 ┆ 有 ┆ 謙 ┆ 戮 ┆ 那 ┆   ┆ 大 ┆   ┆ 始 ┆ 然 ┆
┆ 薄 ┆ 一 ┆ 臨 ┆ 你 ┆ 的 ┆ 還 ┆ 沒 ┆   ┆ 來 ┆   ┆ 是 ┆ 來 ┆ 遜 ┆ 沒 ┆ 些 ┆   ┆ 雁 ┆   ┆ 終 ┆ 而 ┆
┆   ┆ 暖 ┆   ┆ 如 ┆ 地 ┆ 站 ┆ 有 ┆   ┆ 也 ┆   ┆ 我 ┆   ┆ 的 ┆ 有 ┆ 精 ┆   ┆ 也 ┆   ┆ 沒 ┆ 你 ┆
┆   ┆ 這 ┆   ┆ 試 ┆ 方 ┆ 在 ┆ 逃 ┆   ┆ 會 ┆   ┆ 在 ┆   ┆ 清 ┆ 來 ┆ 準 ┆   ┆ 沒 ┆   ┆ 有 ┆ 沒 ┆
┆   ┆ 生 ┆   ┆ 探 ┆   ┆ 最 ┆ 避 ┆   ┆ 在 ┆   ┆ 這 ┆   ┆ 晨 ┆   ┆ 的 ┆   ┆ 有 ┆   ┆ 來 ┆ 有 ┆
┆   ┆ 之 ┆   ┆ 般 ┆   ┆ 不 ┆   ┆   ┆ 這 ┆   ┆ 裏 ┆   ┆ 沒 ┆   ┆ 殺 ┆   ┆ 來 ┆   ┆   ┆ 來 ┆

以LeetCode為例重慶幸運農場——如何發送GraphQL Query獲取數據