【Java与网络2】:HTTP核心知识与Curl工具

HTTP是当前应用最为广泛的通信协议,我们上网、玩游戏、刷视频、查美食都离不开HTTP协议。当我们做开发的时候, 需要经常和H5、Android、IOS、PC前端等不同团队的同学打交道,大家讨论的核心问题之一就是交互的时候协议怎么定,而这个协议基本都是HTTP协议。

本文我们就来梳理一下HTTP的重要内容。

1.HTTP到底是什么

HTTP是一个属于应用层的面向对象的协议,最大的好处是简单、高效、易懂。不需要看UDP等那么复杂的协议,地球人等都能看懂。由于其简捷、快速的方式,适用于分布式超媒体信息系统。它于1990年提出,之后几十年,使用越来越广,也得到不断地完善和扩展。 

HTTP 全名是超文本传输协议,也就是HyperText Transfer Protocol。估计很多人一看这个名字就蒙了,什么叫超文本、什么是传输,什么是协议?

1.1.什么是协议

先来看协议,所谓的协议,就是双方的约定,例如你和女朋友约定周末去看电影,这个就是协议。

在生活中,我们也能随处可见「协议」,例如:

  • 刚毕业时会签一个「三方协议」;
  • 找房子时会签一个「租房协议」;

小到个人,大到国家、大型设施,而如果协议没安排好,就会出现很多问题。例如著名的国际空间站因为参与国家多、周期长等多种原因,导致在结构上有很多的冗余,这也带来了巨大的浪费。而中国的空间站在充分参考了前者的经验教训,从一开始就进行周密的设计和落实,因此中国空间站的体积只有国际空间站的1/4,但是能承载的实验能力是后者的75%,这就是好的协议的典型应用。

而不同的计算机进行通信的时候,也需要共同确定一个规则,大家都遵守这个规范就可以非常方便的协同工作。其中在应用层,大家都认可的协议就是HTTP。所以说HTTP 是一个用在计算机世界里的协议。它使用计算机能够理解的语言确立了一种计算机之间交流通信的规范(两个以上的参与者),以及相关的各种控制和错误处理方式(行为约定和规范)。

1.2.什么是传输

很好理解,就是把一堆东西从 A 点搬到 B 点,或者从 B 点 搬到 A 点。

这也说明HTTP 协议是一个双向协议,而我们收听广播、看电视则是单向的协议。我们在上网冲浪时,浏览器是请求方 A,百度网站就是应答方 B。双方约定用 HTTP 协议来通信,于是浏览器把请求数据发送给网站,网站再把一些数据返回给浏览器,最后由浏览器渲染在屏幕,就可以看到图片、视频了。

另外,就是数据虽然是在 A 和 B 之间传输,但允许中间有中转或接力。就好像第一排的同学想传递纸条给最后一排的同学,记得笔者在上中学的时候,班级里谈恋爱的同学,经常偷偷让人给递纸条,有的时候还要多个人给递才可以,就是这种场景。

那么传递的过程中就需要经过好多个同学(中间人),这样的传输方式就从「A < --- > B」,变成了「A <-> N <-> M <-> B」。

而在 HTTP 里,需要中间人遵从 HTTP 协议,只要不打扰基本的数据传输,就可以添加任意额外的东西。因此,HTTP 是一个在计算机世界里专门用来在两点之间传输数据的约定和规范。

1.3.什么是超文本

我们先来理解「文本」,在互联网早期的时候只是简单的字符文字,但现在「文本」的涵义已经可以扩展为图片、视频、压缩包等,在 HTTP 眼里这些都算作「文本」。

再来理解「超文本」,它就是超越了普通文本的文本,它是文字、图片、视频等的混合体,最关键有超链接,能从一个超文本跳转到另外一个超文本。

HTML 就是最常见的超文本了,它本身只是纯文字文件,但内部用很多标签定义了图片、视频等的链接,再经过浏览器的解释,呈现给我们的就是一个文字、有画面的网页了。

OK,经过了对 HTTP 里这三个名词的详细解释,就可以给出比「超文本传输协议」这七个字更准确更有技术含量的答案:

HTTP 是一个在计算机世界里专门在「两点」之间「传输」文字、图片、音频、视频等「超文本」数据的「约定和规范」。

也就是说,HTTP不仅仅可以传输文本,还可以传输图片视频等等,这就是超文本的含义。

HTTP协议的主要特点可概括如下:

  1. 支持客户/服务器模式。
  2. 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、HEAD、POST。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
  3. :HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
  4. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。
  5. 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

2.HTTP协议的结构

2.1 基本结构

  http(超文本传输协议)整体是一个基于请求与响应模式的、无状态的、应用层的协议,但是需要注意HTTP在工作的时候常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。

HTTP URL (URL是一种特殊类型的URI,包含了用于查找某个资源的足够的信息)的格式如下:

  https://host[":"port][abs_path]

 http表示要通过HTTP协议来定位网络资源;

  • host表示合法的Internet主机域名或者IP地址;
  • port指定一个端口号,为空则使用缺省端口80;
  • abs_path指定请求资源的URI;如果URL中没有给出abs_path,那么当它作为请求URI时,必须以“/”的形式给出。例如:

https://www.baidu.com/

2.2 HTTP请求消息的结构

 http请求由三部分组成,分别是:请求行、消息报头、请求正文

  1、请求行以一个方法符号开头,以空格分开,后面跟着请求的URI和协议的版本,格式如下:Method Request-URI HTTP-Version CRLF

  其中 Method表示请求方法;Request-URI是一个统一资源标识符;HTTP-Version表示请求的HTTP协议版本;CRLF表示回车和换行(除了作为结尾的CRLF外,不允许出现单独的CR或LF字符)。

  请求方法(所有方法全为大写)有多种,各个方法的解释如下:  

       GET 请求获取Request-URI所标识的资源

  POST 在Request-URI所标识的资源后附加新的数据

  HEAD 请求获取由Request-URI所标识的资源的响应消息报头

  PUT 请求服务器存储一个资源,并用Request-URI作为其标识

  DELETE 请求服务器删除Request-URI所标识的资源

  TRACE 请求服务器回送收到的请求信息,主要用于测试或诊断

  CONNECT 保留将来使用

  OPTIONS 请求查询服务器的性能,或者查询与资源相关的选项和需求

  get应用举例:

http://127.0.0.1:19988/api/inner/user_points_activity/detail?user_id=203527702&points_activity_id=2&biz_type=212&biz_id=676&kav=25

 post举例:

一般来说,get请求主要用于做简单的查询,请求的参数可以在url地址上一直拼接。而post一般用于提交修改,或者查询条件比较复杂的时候使用。

例如我们使用百度查询的时候,请求的结构如下:

2.3 HTTP响应的结构

 在接收和解释请求消息后,服务器返回一个HTTP响应消息。HTTP响应也是由三个部分组成,分别是:状态行、消息报头、响应正文。

  状态行格式如下

  HTTP-Version Status-Code Reason-Phrase CRLF

  其中,HTTP-Version表示服务器HTTP协议的版本;Status-Code表示服务器发回的响应状态代码;Reason-Phrase表示状态代码的文本描述。

  状态代码有三位数字组成,第一个数字定义了响应的类别,且有五种可能取值:

  •   1xx:指示信息--表示请求已接收,继续处理
  •   2xx:成功--表示请求已被成功接收、理解、接受
  •   3xx:重定向--要完成请求必须进行更进一步的操作
  •   4xx:客户端错误--请求有语法错误或请求无法实现
  •   5xx:服务器端错误--服务器未能实现合法的请求

  常见状态代码、状态描述、说明:

  •   200 OK //客户端请求成功,我们最喜欢的相应
  •   400 Bad Request //客户端请求有语法错误,不能被服务器所理解
  •   401 Unauthorized //请求未经授权,这个状态代码必须和WWW-Authenticate报头域一起使用
  •   403 Forbidden //服务器收到请求,但是拒绝提供服务,一般这个会和401混着用
  •   404 Not Found //请求资源不存在,eg:输入了错误的URL
  •   500 Internal Server Error //服务器发生不可预期的错误
  •   503 Server Unavailable //服务器当前不能处理客户端的请求,一段时间后可能恢复正常

除了上述状态码,还有很多,这个一般我们也记不住,记住了也没用,如果在工作中遇到了,直接查一下就好。例如笔者工作时,曾经遇到响应是429的情况,查阅后发现是因为请求参数太长了,对方给拒绝了,对于这类问题,我们就不必太矫正了。

2.4 HTTP 常见字段

本部分摘自小林coding

Host 字段

客户端发送请求时,用来指定服务器的域名。有了 Host 字段,就可以将请求发往「同一台」服务器上的不同服务。

Content-Length 字段

服务器在返回数据时,会有 Content-Length 字段,表明本次回应的数据长度。

如上面则是告诉浏览器,本次服务器回应的数据长度是 1000 个字节,后面的字节就属于下一个回应了。

Connection 字段

Connection 字段最常用于客户端要求服务器使用「HTTP 长连接」机制,以便其他请求复用。HTTP 长连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。HTTP/1.1 版本的默认连接都是长连接,但为了兼容老版本的 HTTP,需要指定 Connection 首部字段的值为 Keep-Alive,也就是传输的时候要带这么个字段:

Connection: Keep-Alive

开启了 HTTP Keep-Alive 机制后, 连接就不会中断,而是保持连接。当客户端发送另一个请求时,它会使用同一个连接,一直持续到客户端或服务器端提出断开连接。

这里看到长链接,我们会想HTTP里的长链接与TCP里的长连接是一回事吗?直觉告诉我们应该不是一回事。小林的这篇文章写的很不错,建议参考。

Content-Type 字段

Content-Type 字段用于服务器回应时,告诉客户端,本次数据是什么格式。

Content-Type: text/html; Charset=utf-8

上面的类型表明,发送的是网页,而且编码是UTF-8。

客户端请求的时候,可以使用 Accept 字段声明自己可以接受哪些数据格式。

Accept: */*

上面代码中,客户端声明自己可以接受任何格式的数据。

Content-Encoding 字段

Content-Encoding 字段说明数据的压缩方法。表示服务器返回的数据使用了什么压缩格式。

Content-Encoding: gzip

上面表示服务器返回的数据采用了 gzip 方式压缩,告知客户端需要用此方式解压。

客户端在请求时,用 Accept-Encoding 字段说明自己可以接受哪些压缩方法。

Accept-Encoding: gzip, deflate

3 Curl工具介绍

对于网络,我们更多是在实践中应用,其中cURL是在命令行下工作的文件传输工具。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。

cURL还包含了用于程序开发的libcurl。

curl支持的协议非常多,cURL支持的通信协议有: FTP、FTPS、HTTP、HTTPS、TFTP、SFTP、Gopher、SCP、Telnet、DICT、FILE、LDAP、LDAPS、IMAP、POP3、SMTP和RTSP。 curl还支持SSL认证、HTTP POST、HTTP PUT、FTP上传, HTTP form based upload、proxies、HTTP/2、cookies、用户名+密码认证(Basic, Plain, Digest, CRAM-MD5, NTLM, Negotiate and Kerberos)、file transfer resume、proxy tunneling。

3.1 Curl使用

在每一个HTTP请求中,都有一个对应的方法,常用的方法有:GET、POST、HEAD和PUT。

如果在一个curl命令中不指定具体的方法,那么默认的就是使用GET方法。对于其它的方法,可以在curl命令中指定:

methodoption
POST-d或-F
HEAD-I
PUT-T

在curl中,使用 -i 选项可以显示Response的Header信息,连同Body数据:

$ curl -i www.baidu.com

结果如下:

使用 -I 选项可以只显示Response的Header信息:

$ curl -I www.baidu.com

3.2 POST 请求相关问题      

POST是HTTP中向服务端提交数据的一种方法。

在浏览器中,但在表单中填写完数据后,浏览器就会默认将填写的数据使用 key=value 串的形式进行转化。

在curl中,我们可以使用 -d 或 –data 选项来指定具体的数据:

$ curl -d key1=value1&key2=value2 http://example.com

我们也可以使用多个 -d 选项来指定多组数据,curl会自动把这些数据连接起来,因此上面的例子还可以这样:

$ curl -d key1=value1 -d key2=value2 http://example.com

当然,如果数据过多,我们还可以把数据放在一个文件中:

$ curl -d @filename http://example.com
Content-Type

当使用POST方法提交数据时,对于提交的数据主要有如下四种形式:

  • application/x-www-form-urlencoded:默认的形式,即key1=value1&key2=value2的形式;
  • multipart/form-data:使用表单上传文件时使用这个形式;
  • application/json:提交JSON格式的数据;
  • text/xml:提交XML格式的数据。

Content-Type是一个Header,如果不指定的话,那么默认就是使用application/x-www-form-urlencoded形式传输数据,

当需要使用别的形式进行数据传输的话,那么就需要指定这个Header:

$ curl -d '{I Am A JSON FORM}' -H 'Content-Type: application/json' http://example.com

其中,-H就是用来指定一个具体的Header的选项,值就是key=value 的形式。当需要指定其它的Header,可以使用-H选项。

POST一个二进制数据

在curl中,我们也可以提交一个文件,可以使用–data-binary选项来指定一个文件:

$ curl --data-binary @filename http://example.com
转化成一个GET

使用-G-get选项,可以把一个POST请求转化成一个GET请求。如果有-d选项指定的参数,那么curl就会把-d后面的数据添加到URL的后面,用?连接。比如:

$ curl -d "key1=value1" -G http://example.com

得到的请求URL就是:

http://example.com/?key1=value1
URL编码

如果使用的数据没有编码,那么可以指定curl来帮助自己进行编码。这时可以使用 –data-urlencode 选项来指定。比如:

$ curl --data-urlencode "name=Alan Walker" http://example.com
multipart formposts

如果一个HTTP POST具有如下形式的表单:

<form action="submit.cgi" method="post" enctype="multipart/form-data">
    Name: <input type="text" name="person"><br>
    File: <input type="file" name="secret"><br>
    <input type="submit" value="Submit">
</form>

用户可以在Name中填写名字,在File中选择一个文件,然后单击Submit按钮提交数据。

为了可以在curl中模拟这个请求,我们可以使用-F–form选项来指定数据:

$ curl -F person=annonymous -F secret=@filename http://example.com/submit.cgi

在上面的表单中,action指定了这个请求发送到哪里;method指定这是一个POST请求;而enctype指定了这是一个multipart formpost

当执行上面的curl命令后,curl会产生如下的请求头:

POST /submit.cgi HTTP/1.1
Host: example.com
User-Agent: curl/7.46.0
Accept: */*
Content-Length: 313
Content-Type: multipart/form-data; boundary=------------------------d74496d66958873e

其中Content-Type是和enctype一致的。

当使用-F选项时,默认的Content-Type就是multipart/form-data,不过,我们也可以使用-H进行指定:

$ curl -F 'name=Dan' -H 'Content-Type: multipart/magic' https://example.com
-d vs -F

在前面我们介绍了使用-d构造一个基本的POST请求,和-F构造一个multipart formpost请求。那么这两个选项有啥区别以及什么时候使用呢?

这两个选项都是把指定的数据发送到服务器上,区别在于数据传递的格式。大多数时候,接收端来指定希望客户端发送数据的格式,客户端不能随意自己指定格式。

  • HTML表单

当使用HTML表单时,会使用

标签指定一个表单,这会让浏览器使用POST方法。如果标签中含有enctype=multipart/form-data

这意味着使用multipart formpost方式,在curl中就是使用-F选项。一个典型的场景就是表单中含有标签。

  • 不用HTML表单

POST方法不一定非要在HTML中,在好多的service、APIs中,也可以使用POST请求。

如果这些service期望使用JSON或者其它类似的格式的数据,那么这就是一个普通的POST请求。

在curl中就可以使用-d选项。不过要注意-d的默认Content-Type是不是期望的格式,如果不是的话,可以使用-H进行更改。

HTTP重定向(redirect)

重定向是HTTP协议中的一个基础部分。在重定向中,服务器给客户端的并不是客户端想要的内容,

而是一个车具体的指令,告诉客户端如果想获取想要的数据,应该到哪里去请求。

但不是所有的重定向都一样。重定向之后的请求使用什么方法呢?重定向多久呢?

所有的重定向都会返回Location:的Header,来指定一个新的URL。

curl:redirect

在curl中,默认不会重定向,可以使用-L或–location选项来告诉curl重定向:

$ curl -L http://example.com
GET还是POST

第一次请求后,服务器会告诉客户端下一次请求需要使用的方法。关于重定向的响应码如下:

MethodPermanentTemporary
切换到GET301302和303
使用第一次请求的方法308307

我们可以指定curl在重定向时使用什么方法。

如果我们第一次请求使用的不是GET方法,重定向后也不希望curl默认使用GET方法,那么我们可以使用–post301,–post302和–post303选项来指定。

3.3 修改HTTP请求

每一个请求都有一个请求行、一些请求头和可选的请求体,这里我们看看在curl中可以具体修改的部分,包括请求行和请求头。

请求方法

在请求行中包含这次请求所使用的方法。我们使用下面的简单命令就可以进行一个GET方法:

$ curl http://example.com/file

这会生成如下的请求行:

GET /file HTTP/1.1

在HTTP方法中我们可以通过具体的选项指定使用什么方法。这里我们也可以使用-X选项来进行指定:

$ curl -X POST http://example.com
修改请求头

在curl中,我们可以使用-H或–header选项来指定Header。之前我们就使用-H指定了Content-Type,其实Header就是一个key: value对:

$ curl -H "HeaderName: HeaderValue" http://example.com
Referer

我们还可以在curl通过–referer选项来指定我们是从哪里跳转过来的:

$ curl --referer http://fromexample.com http://toexample.com
User Agent

这个字段是用来表示客户端的设备信息的,服务器会根据这个字段,针对不同的设备,返回不同格式的网页。在curl中,可以使用–user-agent选的来指定:

$ curl --user-agent "[User Agent]" http://example.com

3.4 Cookies

HTTP是一种无状态的协议,为了在会话中保存一些状态,可以使用Cookies。服务器通过Set-Cookie:来设置Cookie,客户端就可以在下一次请求中携带这些数据。

设置Cookie

我们可以使用–cookie选项来设置一个Cookie:

$ curl --cookie "CookieName=CookieValue" http://example.com
从文件中读取Cookies

curl默认不会记住服务器设置的Cookie,也不会在下一次请求中携带Cookie。除非用户通过选项自己设置。

我们可以把之前的Cookies保存到一个文件,然后在下一次请求中指定curl读取文件中的Cookies:

$ curl -b cookies.txt http://example.com

-b选项指定curl去给定的文件中读取Cookies。

不过要主要,这里仅仅是读取Cookies,如果这次请求中服务器修改了Cookie,那么curl是不会进行保存的,除非我们手动指定。

写Cookies到文件

我们可以使用-c选项指定curl保存这次请求中服务器设置的Cookies:

$ curl -c cookie.jar.txt http://example.com

有时,我们既需要从文件中读取Cookies,也需要保存服务器设置的Cookies。那么就可以同时使用-b和-c选项:

$ curl -b cookies.txt -c cookie.jar.txt http://example.com

3.5 使用浏览器获得完整的地址

我们前面使用的curl还是比较短的,但是在实际中经常需要设置一大堆的参数,费时费力不说,还非常容易错,如果是现成的接口调用,我们可以从浏览器中直接得到,例如在Chrome浏览器,我们打开More tools->Developer模式,

选择Network选项卡,然后就可以看到所有的请求,选中相应的请求,右键就有Copy as cURL选项,单击就可以了。

复制出来的结果如下:

curl 'https://blog.51cto.com/medal/getUserHaveGetMedalList?user_id=974126' \
  -H 'authority: blog.51cto.com' \
  -H 'accept: application/json, text/javascript, */*; q=0.01' \
  -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8' \
  -H 'cookie: www51cto=3B0395CFCB8E92581AEC8926208372D9GuLZ; Hm_lvt_110fc9b2e1cae4d110b7959ee4f27e3b=1700208396,1701877256; look_course_log=%5B35193%2C34389%2C34187%2C34755%2C34814%2C32806%2C21604%2C24677%5D; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%2218be76c211ce72-0e5d551dbe0218-1e525634-2073600-18be76c211deea%22%2C%22first_id%22%3A%22%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E8%87%AA%E7%84%B6%E6%90%9C%E7%B4%A2%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC%22%2C%22%24latest_referrer%22%3A%22https%3A%2F%2Fwww.baidu.com%2Flink%22%2C%22%24latest_utm_source%22%3A%22hometop%22%7D%2C%22%24device_id%22%3A%2218be76c211ce72-0e5d551dbe0218-1e525634-2073600-18be76c211deea%22%7D; PHPSESSID=ceprumiove5ff1gqei16vv66pm; _csrf=be3601292c4e625a8d9fb4df16a92d8a84a274b0338b30c38bfccd338f1680c8a%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22%97%2Fas%CBgp%80%F1yP%A9-%82%F5%21%D4%88%C9%1F%E3Q%11d%DBH%A9%00%FBE%E0%D1%22%3B%7D; Hm_lvt_2283d46608159c3b39fc9f1178809c21=1703903343,1704900221,1705326322,1705453067; aliyungf_tc=f98cc542b1258b708f0f7c05bf52e0251a886e4c068e03a2c2979a87d8eb7892; cssLoaded=%2Fpcdetail%2Fpcblogger; Hm_lpvt_2283d46608159c3b39fc9f1178809c21=1706196508; ssxmod_itna2=Qqjx2Dy7GQKGuDiq0LAOID0CDgi+rOYqHqID61+BmPx0vr9+q03KPcPOCtCqt0Ap2K4Hq5IYYRHD8o4xmeKik2TeDfowLPCA2nre8CC2QIHqhTRjdTe9YitRnRdjxmgc06sTKxhuecHHYaWkcePOCBKby=GkpO5Odl5TThKOoBa1KDy8D/DOuOG=HoEirRW1qhaADz5kwUGFp=Wf9nW7Y=KmY=Grv/xIvFm5WxI=CB2Xi8Gxd5kYVtWeD1eaX71Q4TB9WEa9/I1hwtmob5AcOZQ=INf6CKemR4wA=utcvMCpzPFEiSe=8eV4A09y1fw6KT6fTrjFxFy4Fv9j97zW1+ieVufCr7I4CCT7fY=/q2KE7ChkCqi8Iz9WKCie6FexYzAhVfrOKpxlywUx=8+O3uaiFACya+PIjBsUTIbPo2ekFi3TfICuU8iaE2BKfTo7OWSougOfxT1vjl3tgmHMO7UwzjvDEwHr7H7fHYMRI864gRKf4cmFy+HIR7CybwH73+MWOltC6zSzNEroY4Ol+NO60k6bgoD07t7PwODqhqO3xMQGh9PwFQl0KqB3Ug3HoOXGcCgcCAwe7KAr4D7=DYFKeD==; acw_tc=ac11000117062327922395479efad375fb8316cd782bb9b8d8374a3c1bfc91; ssxmod_itna=WqGxuD2DBAitG=KGHD8ibeBKRqYwEdLEkGfxqqGNmxoDZDiqAPGhDCbbIbhifwGexPOba74+reFoWoRsE9OYpQeeKiWFvsbWYxiTD4q07Db4GkDAqiOD7wLeDxOq0rD74irDDxD3vHutXueqDHDGpDTL6ZDi3DboiDmqGnD7UZDG3XzeDA7qGSAQXgGeQDGqKoPdWDzfWcQuUlUuQDtTbuWM0Fs=F3KehKTOtDzk78OT=eomNV8Tgxkn53bEq3mAvtS8Gab0x3tBxLaYh58G+0kEmtzDx9=5pzUGDxD=' \
  -H 'referer: https://blog.51cto.com/androidguy/p_7' \
  -H 'sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Google Chrome";v="120"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "macOS"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: same-origin' \
  -H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' \
  -H 'x-requested-with: XMLHttpRequest' \
  --compressed

可以看到实际应用中,参数往往是非常多的,而他浏览器一般都有这样的功能,这样可以大大降低我们的使用难度。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/356565.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

###C语言程序设计-----C语言学习(6)#

前言&#xff1a;感谢老铁的浏览&#xff0c;希望老铁可以一键三连加个关注&#xff0c;您的支持和鼓励是我前进的动力&#xff0c;后续会分享更多学习编程的内容。 一. 主干知识的学习 1. while语句 除了for语句以外&#xff0c;while语句也用于实现循环&#xff0c;而且它…

Android 系统启动流程

依旧是带着问题再去学习 首先&#xff0c;Android是怎么启动的&#xff1f; Android服务是怎么启动的&#xff1f; Android线程是怎么切换的&#xff1f; Android ApplicationThread是怎么创建的&#xff1f; 那么接下来开始分析Android的启动流程 还是一步一图 先画一张流…

day27 回溯算法part3

39. 组合总和 中等 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。 candidates 中的 同一个 数字可以 无限…

外汇天眼:Alpha Group International为股票回购计划拨款高达2,000万英镑

Alpha Group International plc&#xff0c;一家为企业和机构提供金融解决方案的公司&#xff0c;宣布计划启动股票回购程序&#xff0c;以购买每股面值为0.2便士的普通股。 该公司已经从其现金储备中拨款高达2,000万英镑用于回购计划。购买的普通股将被保留在公司的资本中。 …

合并有序链表---链表OJ---归并思想

https://leetcode.cn/problems/merge-two-sorted-lists/?envTypestudy-plan-v2&envIdtop-100-liked 将两个有序的链表合并为一个新的有序链表&#xff0c;那不就是和归并排序中最后合并的思想一样吗&#xff1f;只不过那里合并的是数组&#xff0c;这里合并的是链表。 首先…

数据分析入门指南:用 Python 开启数据之旅

文章目录 前言发现宝藏为什么选择 Python 进行数据分析&#xff1f;准备工作数据分析基础1. 数据加载2. 数据探索3. 数据清洗4. 数据可视化 探索更多可能性好书推荐总结 前言 为了巩固所学的知识&#xff0c;作者尝试着开始发布一些学习笔记类的博客&#xff0c;方便日后回顾。…

小程序直播項目开发流程

点击登录功能&#xff0c;创建IM个人账户 以及 创建直播间群组 第一步&#xff1a;需要获取用户唯一的标识openid。 获取流程如下-点击登录按钮-通过wx.getUserProfile这个Api返回的res.userinfo信息获取用户头像昵称等-再通过wx.login的api获取用户的code-使用code再到服务器换…

【开源】基于JAVA的房屋出售出租系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 房屋销售模块2.2 房屋出租模块2.3 预定意向模块2.4 交易订单模块 三、系统展示四、核心代码4.1 查询房屋求租单4.2 查询卖家的房屋求购单4.3 出租意向预定4.4 出租单支付4.5 查询买家房屋销售交易单 五、免责说明 一、摘…

单片机学习笔记---定时器计数器(含寄存器)工作原理介绍(详解篇1)

目录 51内部定时计数器概述 定时器和计数器概念的区分 定时计数器的结构框图 定时计数器的控制字 M1和M0工作方式选择位的四种工作方式 总结 51内部定时计数器概述 先概述一下&#xff0c;51内部是有两个16位的定时计数器&#xff0c;这个16位指的是它定时计数的常数是1…

4秒读取50w行Excel数据

4秒读取50w行Excel数据 文章比较了几种常用的读取Excel的方法&#xff0c;最终发现rust库Calamine的速度最快&#xff0c;可以在4秒内读取50w行excel数据。 原文&#xff1a;Fastest Way to Read Excel in Python&#xff1a;https://hakibenita.com/fast-excel-python 我们在…

React16源码: React中处理LegacyContext相关的源码实现

LegacyContext 老的 contextAPI 也就是我们使用 childContextTypes 这种声明方式来从父节点为它的子树提供 context 内容的这么一种方式遗留的contextAPI 在 react 17 被彻底移除了&#xff0c;就无法使用了那么为什么要彻底移除这个contextAPI的使用方式呢&#xff1f;因为它…

openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题

文章目录 openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题209.1 共享内存泄露问题209.1.1 问题现象209.1.2 原因分析209.1.3 处理方法 openGauss学习笔记-209 openGauss 数据库运维-常见故障定位案例-共享内存泄露问题 209.1 共享内存泄露问题…

【Web前端实操18】粘性定位——即固定顶层内容,可以继续滚动,但是顶层内容固定,不随着一起滚动

粘性定位 1、了解 可以被认为是相对定位和固定定位的混合。元素在跨越特定阈值前为相对定位,之后为固定定位。粘性定位是指网页或移动应用程序中的一种特性,即当用户滚动页面时,某个元素能够保持在屏幕上特定位置不动,直到用户滚动到达一定位置或进行特定操作。这个特性可…

Qt无边框窗口拖拽和阴影

先看下效果&#xff1a; 说明 自定义窗口控件的无边框,窗口事件由于没有系统自带边框,无法实现拖拽拉伸等事件的处理,一种方法就是重新重写主窗口的鼠标事件&#xff0c;一种时通过nativeEvent事件处理。重写事件相对繁琐,我们这里推荐nativeEvent处理。注意后续我们在做win平…

2.3_8 多生产者-多消费者问题

2.3_8 多生产者-多消费者问题 实现思路 semaphore mutex1; //实现互斥访问盘子(缓冲区) semaphore apple0; //盘子中有几个苹果 semaphore orange0; //盘子中有几个橘子 semaphore plate 1; //盘子中还可以放多少个水果dad(){while(1){准备一个苹果;P(plate);P(mutex);把苹果放…

网络相关知识

关于作者&#xff1a;CSDN内容合伙人、技术专家&#xff0c; 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 &#xff0c;擅长java后端、移动开发、商业变现、人工智能等&#xff0c;希望大家多多支持。 目录 一、导读二、概览三、相关工具3.1 network profiler/ In…

休息日的思考与额外题——链表

文章目录 前言链表知识点 一、 92. 反转链表 II二、21. 合并两个有序链表总结 前言 一个本硕双非的小菜鸡&#xff0c;备战24年秋招&#xff0c;计划二刷完卡子哥的刷题计划&#xff0c;加油&#xff01; 二刷决定精刷了&#xff0c;于是参加了卡子哥的刷题班&#xff0c;训练…

构建知识图谱:从技术到实战的完整指南

目录 一、概述二、知识图谱的基础理论定义与分类核心组成历史与发展 三、知识获取与预处理数据源选择数据清洗实体识别 四、知识表示方法知识表示模型RDFOWL属性图模型 本体构建关系提取与表示 五、知识图谱构建技术图数据库选择Neo4jArangoDB 构建流程数据预处理实体关系识别图…

详谈掼蛋两大类牌型

掼蛋中的10种牌型&#xff0c;总体上可以分为炸弹牌型系列和普通牌型两大类。炸弹牌型系列包括天王炸、同花顺和多头炸3大类&#xff1b;普通牌型系列包括单张、对子、三同张、三带二、顺子、三连对、连三张等7种牌型。 一、两类牌型的区别 炸弹牌型系列和普通牌型系列两大类有…

信创条件下的运维思考-驱动数字化转型,塑造企业未来之篇章

2024-01-14 12:59 发布于&#xff1a;山西省 运维信创&#xff1a;驱动数字化转型&#xff0c;塑造企业未来之篇章 随着信息技术的迅猛发展&#xff0c;数字化转型已成为企业生存和发展的必由之路。在数字化转型的过程中&#xff0c;运维作为企业IT的重要组成部分&#xff…