免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动!
内容参考于:图灵Python学院
本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要盲目相信。
工具下载:
链接:https://pan.baidu.com/s/1rEEJnt85npn7N38Ai0_F2Q?pwd=6tw3
提取码:6tw3
复制这段内容后打开百度网盘手机App,操作更方便哦
上一个内容:10.安卓逆向-安卓开发基础-api服务接口设计1
上一个内容里通过OkHttp3实现了post和get请求,本次接着上一个内容继续
实现搜索爬虫
爬虫做的事是把下图红框的数据读取出来放到ui界面中,下图的链接在上一个内容中
创建一个Empty Activity
先写ui界面,如下图样子
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".HttpSearch"> <EditText android:id="@+id/editText1" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="请输入搜索页码" android:inputType="text" /> <Button android:id="@+id/button1" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="提交" /> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" /> <TextView android:id="@+id/text1" android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="18sp" android:textColor="@android:color/black" /> </LinearLayout>
要注意下图红框位置的内容,要与Activity名字一样
然后修改清单文件
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.course1"> <uses-permission android:name="android.permission.INTERNET" /> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:networkSecurityConfig="@xml/network_security_config" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/Theme.Course1"> <activity android:name=".HttpSearch" android:exported="true" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name=".OkHttp3Dome" android:exported="false"> <!-- <intent-filter>--> <!-- <action android:name="android.intent.action.MAIN" />--> <!-- <category android:name="android.intent.category.LAUNCHER" />--> <!-- </intent-filter>--> </activity> <activity android:name=".liebiao" android:exported="false"> <!-- <intent-filter> --> <!-- <action android:name="android.intent.action.MAIN" /> --> <!-- <category android:name="android.intent.category.LAUNCHER" /> --> <!-- </intent-filter> --> </activity> <activity android:name=".tiaozhuan2" android:exported="false" /> <activity android:name=".tiaozhuan1" android:exported="true"> <!-- <intent-filter> --> <!-- <action android:name="android.intent.action.MAIN" /> --> <!-- <category android:name="android.intent.category.LAUNCHER" /> --> <!-- </intent-filter> --> </activity> <activity android:name=".MainActivity2" android:exported="false" /> <activity android:name=".MainActivity" android:exported="false"> <!-- <intent-filter> --> <!-- <action android:name="android.intent.action.MAIN" /> --> <!-- <category android:name="android.intent.category.LAUNCHER" /> --> <!-- </intent-filter> --> </activity> </application> </manifest>
然后Activity里的代码
package com.example.course1; import androidx.appcompat.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import java.io.IOException; import java.util.ArrayList; import okhttp3.Call; import okhttp3.Callback; import okhttp3.FormBody; import okhttp3.Headers; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import okhttp3.internal.http2.Header; public class HttpSearch extends AppCompatActivity { private EditText mEditText; private Button mButton; ListView listView; public OkHttpClient client = new OkHttpClient(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_http_search); mEditText = findViewById(R.id.editText1); mButton = findViewById(R.id.button1); listView = findViewById(R.id.listView2); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String text = mEditText.getText().toString(); sendRequest(text); } private void sendRequest(String page) { new Thread(new Runnable() {// new Thread是开启一个新的线程,去执行代码,运行代码的东西被称为线程,这样写为了高性能 @Override public void run() { // 创建请求对象,也就是告诉OKHTTP3要访问的连接地址和参数是什么 FormBody formBody = new FormBody.Builder() // 构建给服务器发送的数据 // .add("pageNum","1") .add("pageNum", page) .add("pageSize", "30") .add("column", "szse") .add("tabName", "fulltext") .add("plate", "") .add("stock", "") .add("searchkey", "") .add("secid", "") .add("category", "category_gddh_szsh") .add("trade", "") .add("seDate", "2024-03-22~2024-09-23") .add("sortName", "") .add("sortType", "") .add("isHLtitle", "").build(); Request request = new Request.Builder() .url("http://www.cninfo.com.cn/new/hisAnnouncement/query") // 设置请求的 URL .post(formBody) // 设置post请求的请求参数(也就是通过post的方式给服务器发送的数据) .addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")// 设置请求头 .build(); // newCall请求地址,enqueue里面是请求成功还是失败 client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { // 请求失败会执行这个方法,一般服务器报错会来到这个方法中 // 请求失败,处理错误 e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { // 执行成功会执行这个方法 // 请求成功,处理响应数据 if (response.isSuccessful()) { String responseData = response.body().string(); try { JSONObject jsonObject = new JSONObject(responseData); JSONArray announcements = (JSONArray) jsonObject.get("announcements"); ArrayList<String> list = new ArrayList<>(); for (int i = 0; i < announcements.length(); i++) { jsonObject = (JSONObject) announcements.get(i); list.add(jsonObject.get("secName").toString()); System.out.println(jsonObject.get("secName").toString()); } showResponse(list);// 调用 showResponse 把数据放到 ListView 里 Headers headers = response.headers(); for (int i = 0; i < headers.size(); i++) { System.out.println(headers.name(i) + ": " + headers.value(i)); // 获取响应头 } } catch (JSONException e) { e.printStackTrace(); } // System.out.println(responseData); // 在这里处理响应数据 } else { // 请求失败,处理错误 // 可以根据 response.code() 判断具体的失败原因 } } }); } private void showResponse(final ArrayList list){ runOnUiThread(new Runnable() {// 在非主线程中修改界面里的内容需要使用 runOnUiThread @Override public void run() { MyAdapter myAdapter = new MyAdapter(list); listView.setAdapter(myAdapter);// 把爬到的数据放到ListView里 } }); } }).start(); } }); } }
除了修改了上方刚创建的Activity,还修改了下图红框里的内容
效果图:输入2,然后点提交就会把接口返回的数据放到ListView里,这个2是页数,通过分析接口返回的数据得到的,如果不知道怎么分析是正常的,还没开始搞分析数据
获取响应头
然后是拦截器
如下图红框,调用链接请求服务器是会带着下图红框里的内容(不同网页内容都不一样,都是根据功能业务来的)去访问服务器,有的服务器会校验里面的内容,比如校验是否登录了,Request是请求头,请求服务器的时候会带着,Response一般是响应头是服务器给的,拦截器就是为了设置请求头和响应头的,它会在访问服务器或服务器处理完请求返回到客户端之前拦截下来进行处理,处理一般就是设置请求头和响应头
拦截器使用代码
设置请求头
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { // 获取原始请求 Request originalRequest = chain.request(); // 创建一个新的请求,添加或修改请求头 Request modifiedRequest = originalRequest.newBuilder() // 示例: .addHeader("Authorization", "Bearer your_access_token") .addHeader("User-Agent", "YourApp/1.0") .addHeader("aaaaaa", "cajlkcjklj") .build(); // 继续请求链路,但使用修改后的请求 return chain.proceed(modifiedRequest); } }) .build();
设置响应头
OkHttpClient client = new OkHttpClient.Builder() .addInterceptor(new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { Response originalResponse = chain.proceed(chain.request()); // 添加自定义响应头 originalResponse = originalResponse.newBuilder() // 设置请求头 .header("Custom-Header", "YourValue") // 添加请求头 .addHeader("sdfsdf", "4214532453") .build(); return originalResponse; } }) .build();
上方的代码不全,只有手写的代码
完整代码:
链接:https://pan.baidu.com/s/1W-JpUcGOWbSJmMdmtMzYZg?pwd=q9n5
提取码:q9n5
复制这段内容后打开百度网盘手机App,操作更方便哦