Okhttp模拟爬虫登陆 |青训营笔记
这是我参与「第四届青训营 」笔记创作活动的的第3天
Okhttp是一个由Square公司贡献的网络请求库,相较于HttpUrlConnection,他具有更为丰富的使用方法等。本文主要介绍Okhttp的基本使用以及使用okhttp模拟爬虫的示例。
本文将主要分文以下部分
- okhttp中基本请求的构建
- okhttp在安卓中使用的注意事项
- okhttp中cookieJar的使用
okhttp中基本请求的构建
-
get请求的构建
- 创建httpclient
- 创建request请求
- 使用httpclient发起一个会话,使执行请求并获response,用soup等库解析回应
var httpclient: OkHttpClient = OkHttpClient.Builder() .cookieJar(ck) .build() //这里的cookieJar是用来保存cookies的,后面会具体讲 var request= Request.Builder() //这里替换为相应的url .url($urlLine) .addHeader("User-Agent" , "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36", ) .get() .build() var firstresponse=httpclient.newCall(request).execute() //执行请求
如果需要在get请求中添加数据,一般直接添加到url后面,格式为
$url?key1=value1&key2=value2...
-
post请求的构建
post请求的构建基本与get相同,但是众所周知post请求是需要上传数据的,所以post请求会有一个数据的载体,Java中有很多这种构建这种载体的类,这里不在赘述,简单的写一种实现
val builder = MultipartBody.Builder().setType((MultipartBody.FORM));
builder.addFormDataPart(key,value)
val requestbody =RequestBody.create(
"application/json; charset=utf-8".toMediaTypeOrNull(),json)
//除了requestbody的构建之外,post请求和get请求基本一致
//在request的build过程中,使用.post(requestbody)来post表单
okhttp在安卓中使用的注意事项
如果在主线程中获取网络请求,可能会因为网络等原因导致程序崩溃,为了保证程序的稳定运行,安卓系统不允许在设计程序时,使用主线程发起网络请求。因此,上述的get和post的请求,都是笔者在new Thread后在子线程中执行的。
当然,okhttp也封装了异步执行的函数,为enqueue。具体使用如下
val call:Call = httpclient().newCall()
call.enqueue()
实际上,在这里的enqueue也是新建了一个线程,但是这个函数得到了很好的封装,所以我们调用起来就会较为方便,不需要再新建一个Thread
但是,大多数情况下,我们获取一个请求的时候,需要对resp进行一定的解析,并且会将解析结果作为函数的一个返回值返回来当做这次网络请求的结果。如果主线程已经结束,而网络请求子线程依旧咱进行,在进行return操作的时候,值就会错误传递(在赋值之前就已经返回),对于enqueue这样的封装函数,不方便对其线程操作进行“加装”,所以虽然较为麻烦,一般采用thread,并将thread join到主线程之中,保证值得传递,或者使用promise Future模式,基于此进行线程之间的保证赋值。
okhttp中cookieJar的使用
在进行爬虫开发的过程中,很多网站是需要登陆才能进行操作的,所以学会使用的session保持是非常重要的,在okhttp中,也有相应的cookieJar来帮助我们保存和实现session保持操作
因为具体开发过程中,cookies的设置是较为复杂的,所以我们在进行爬虫模拟之前,应当先对正常网络请求抓包,分析登陆过程中在那个请求中设置了本地的cookies,具体登陆信息数据是怎么处理提交到服务器之中的,是否加盐?加盐之后采取什么样的加密方式,这些都应当在网络分析请求以及适当读网页前端代码的情况下分析。okhttp中的cookJar一般在分析完请求的情况下,重写自己的cookieJar,来满足实际使用中的需求, 下面是我写的一个爬虫的cookieJar的实例。
//因为经过分析,在第一次向服务器获取盐的过程中,cookie被设置且之后的请求中都使用此cookie,所以这个cookieJar的重写逻辑为只在第一次发起请求时保存cookie,后续的请求全都使用当前cookie
class myCookieJar: CookieJar{
var cj:List<Cookie> = listOf()
override fun loadForRequest(url: HttpUrl): List<Cookie> {
return this.cj
}
override fun saveFromResponse(url: HttpUrl, cookies: List<Cookie>) {
if (this.cj.isEmpty()){
this.cj = cookies
}
}
在捕捉网页登陆请求时,一般网页在成功登陆后会进行迅速进行跳转,网络请求记录也会被清除,我们很难对网络请求的过程进行分析记录,所以一般在分析的过程中,我们先使用错误的账号密码对网络请求进行捕获分析,然后模拟请求,如果得到和网页中一样的响应,即模拟成功,然后再使用正确的信息进行登陆模拟
最后,爬虫应符合网站相应的规定,不能进行违法犯罪行为。网络并非法外之地。