0%

Lava2×HTTP请求

原因是上篇文章写的教程,用Java连接Lava的RPC发送请求,结果却失败了。

百思不得其解,所以决定好好的琢磨一下如何写HTTP请求。

我们已经知道一个简单的概念:

客户端(发送请求)——>服务器(处理请求)——>客户端(收到结果)

为什么使用Java,可能我还是比较执着,认为Java天下第一。

我们使用基于Maven的项目来测试。

(本文默认使用SpringBoot来测试,因为最后我会把他构建成一个项目,而不仅仅只是脚本)

添加依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<!--        单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version> <!-- 根据需要可以调整版本 -->
<!-- <scope>test</scope>-->
</dependency>

<!-- HTTP依赖-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.13</version>
</dependency>

一个单元测试,一个HTTP依赖包,应该够了。

GET请求:

请求一般分为两种,GET和POST。

但是如果按照Restful风格,还可以有PUT、DELETE等请求方式。由于该风格只是建议,不是规范,就不详细说了(有兴趣可以自行搜索资料)。

一般来说,常见的查询等操作都是用GET,他会将请求参数显示在浏览器的地址栏中。

关于表格或大量数据的提交(或者重要数据,如账号登录),一般使用POST,因为浏览器的地址输入的字符是有限的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test
public void get1() {
String url = "https://www.baidu.com/";
try {
// 创建 HttpClient 实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建 HttpPost 请求
HttpGet httpGet = new HttpGet(url);
// 发送请求
HttpResponse response = httpClient.execute(httpGet);
// 获取结果
HttpEntity entity = response.getEntity();
// 打印信息
System.out.println(EntityUtils.toString(entity));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

这就是比较标准的代码。

唯一稍微可能不一样的是,如果是默认的httpClient.execute(httpGet);的生成结果应该是:CloseableHttpResponse execute 。

CloseableHttpResponse是继承HttpResponse和Closeable的,而Closeable并没什么用,就是多抛出了一个IO异常而已。我们可以以为两者是等效的,但是HttpResponse明显符合我的审美,见名知意,简洁高效。

设置请求头:

在一个HTTP请求中,一般分为:请求头Header,请求体Body(参数),请求地址Url,请求方式GET/POST。

此处,我们尝试设置请求头,为此我们换了一个网址测试。(如果你不添加请求头,将无法请求成功。)

HTTPS和HTTP差别不大,默认情况下:一个是443端口一个是80 端口。

Java的好处是,只要他遵守规范,没有人教你也会使用,因为见名知意。

请求头Header,设置Set,所以设置请求头的方法应该是:

1
2
// 设置请求头
httpGet.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36");

就说优雅不,实在是太优雅了。

他用两个String的参数就解决了这个问题,如果需要设置多个写多行就好了。

User-Agent是用户代理(就是你使用什么客户端访问这个网站)。

关于更多信息可以参考这篇文章:爬虫系列-User-Agent(用户代理)是什么以及如何构建User-Agnet代理池

请求头中不止这一个,也有很多的其他东西,可以一个个的资金去尝试。

日志框架:

当你请求的时候会显示一大堆的日志信息,你非常的烦恼,因为他们对于你来说未免太多了,二无用。

所以,你想去掉他们,我搜索了,最后在B站的视频里面找到了一个方法。

原视频:springboot 整合 log4j2 日志服务

去掉SpringBoot自带的日志,在pom中设置如下:

1
2
3
4
5
6
7
8
9
10
11
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<!-- 排除自带的日志框架-->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>

这样可以优雅的去掉大量的无用日志,但是他会遇到下面的问题:

SLF4J: Failed to load class “org.slf4j.impl.StaticLoggerBinder”.
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

他提示找不到日志框架,emmm,我去问GPT,他说提供一个无用的日志框架即可,纳尼!!!

下面是GPT的回答:
SLF4J警告消息 “Failed to load class org.slf4j.impl.StaticLoggerBinder” 是由于SLF4J未能找到绑定器实现类而产生的。通常,这是由于缺少对应的日志框架的实现(如Log4j、Logback等)而引起的。

如果你只是想忽略这些警告信息,而不是真正解决缺失的日志框架实现,你可以添加一个NOP(No Operation)的日志框架实现,以满足SLF4J的要求,但不会产生实际的日志输出。

你可以使用 slf4j-nop 作为NOP实现。在 Maven 项目的 pom.xml 文件中添加以下依赖:

1
2
3
4
5
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.32</version> <!-- 根据需要可以调整版本 -->
</dependency>

添加了这个依赖后,SLF4J会使用NOP实现,从而避免了警告消息的输出。但需要注意的是,这并不会提供实际的日志功能,只是为了消除警告消息。

完美解决问题,但是谁能告诉我,这是哪个鬼想写出来的方法!!!

POST请求:

艹,怎么请求都有问题。所以,我决定了用python。

毕竟,py才是写爬虫的正规框架。

比如,本来用java写,无论如何都出的问题,用py一下子解决了。

原java代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@Test
public void post2(){
String url = "http://eth1.lava.build/lava-referer-32e55079-2ffe-4611-b5d0-492de8d3b70d/";
try {
// 创建 HttpClient 实例
CloseableHttpClient httpClient = HttpClients.createDefault();
// 创建 HttpPost 请求
HttpPost httpPost = new HttpPost(url);
// 设置请求头
httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36");
httpPost.setHeader("Accept", "*/*");
// 设置请求体
String requestBody = "{\"jsonrpc\":\"2.0\",\"method\":\"eth_chainId\",\"params\":[],\"id\":0}";
StringEntity requestEntity = new StringEntity(requestBody);
httpPost.setEntity(requestEntity);
// 发送请求
HttpResponse response = httpClient.execute(httpPost);
// 获取结果
HttpEntity entity = response.getEntity();
// 打印信息
System.out.println(EntityUtils.toString(entity));
} catch (IOException e) {
throw new RuntimeException(e);
}
}

我用某个网站生成的Py代码,一下子就跑通了,优雅。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import requests
from requests.structures import CaseInsensitiveDict
# 设置请求地址
url = "http://eth1.lava.build/lava-referer-32e55079-2ffe-4611-b5d0-492de8d3b70d/"
# 设置请求头
headers = CaseInsensitiveDict()
headers["Content-Type"] = "application/json"
# 设置请求体
data = '{"jsonrpc":"2.0","method":"eth_chainId","params":[],"id":0}'
# 发送请求
resp = requests.post(url, headers=headers, data=data)
# 响应结果
print(resp.status_code)
print(resp.text)

因为我用的都是重量级编辑器,所以他们会自动导入依赖文件。

单独安装请使用命令:

pip install 模块名

网站是这个:https://reqbin.com/

该网站可以模拟在线发送请求,如果你请求成功了,就是要网站上面的工具生成想要语言的代码,我试过生成Java的,结果失败了。

因为我在刚才也试过国内的在线模拟POST请求网站,都不理想,没有一个是成功的,可能是因为服务器在国内的原因。

所以,我用谷歌搜索:POST online Test

第一个结果就是上面的网站。真的说,用英文描述问题去谷歌搜索,比用百度真的好一万倍。

有的时候确实得变通。