爬取LeetCode题目——如何发送GraphQL Query获取数据

前言

  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
885804-20180719223855159-919972190.png
找到 graphql 文件(有好多 graphql 文件,可以依次点击查找自己想要的那个,这里找到包含有题目信息的),从 preview 中我们可以看到 data 返回了题目相关的信息
885804-20180719224356473-18415864.png
  那么,如何构造 GraphQL Query 来获取信息呢?从 Header 中的 Request Payload 中我们可以看到一个query的字段,这是我们要构造的 GraphQL Query 的一个重要信息。
885804-20180719232018633-1699302590.png
  我们并不一开始就用代码来获取题目信息,而是先利用 Postman 来看看如何获取题目信息。右键 Network 下的 graphql 文件—>Copy—>Copy as cURL(bash),如下图所示:
885804-20180719232607953-589650086.png
之后,打开 Postman—>左上角Import—>Paste Raw Text粘贴,从 Body中可以看到,构造好了的 GraphQL Query 与我们在 Request Payload 中看到的 query 的字段相仿(因为有一点需要更改的细节)
885804-20180719233123295-581471877.png
当然,如果不想直接粘贴复制的 cURL,那么我们可以自己在 Postman 中写 Header 和 Body,需要注意的是这边的 Content-Typeapplication/graphql,Body 中的 GraphQL 构造,参照 Request Payload 中的query的字段来构造
885804-20180719233438003-1026573385.png
获取到的结果如下:
885804-20180719233742759-660254344.png
我们在实际中,可能并不需要提供的所有信息,只想要某一部分,那么只需更改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());

    }
}

执行结果:
885804-20180719235031045-199371891.png

转载于:https://www.cnblogs.com/ZhaoxiCheung/p/9333476.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值