整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          json數(shù)據(jù)解析及網(wǎng)絡請求

          json數(shù)據(jù)解析及網(wǎng)絡請求

          文已經(jīng)介紹了ListView和RecyclerView等各種列表控件,在實際的開發(fā)中,會經(jīng)常遇到大批量的數(shù)據(jù)加載和展示的問題,本節(jié)課來具體的學習一下常見的方式和步驟。

          一、json解析

          移動端和服務器交互一般用得較多的數(shù)據(jù)傳遞方式都是 Json 字符串的形式, 保存對象,我們也可以寫成一個 Json 字符串然后存儲。

          常見的解析 Json的方式有Android自帶Json解析器, Gson,F(xiàn)astjson,jackson 等。

          1.0 http://Json.cn工具

          通過一個在線網(wǎng)站工具可以實時的實現(xiàn)json數(shù)據(jù)的格式化:http://www.json.cn/

          1.1 Android自帶的Json解析器

          自帶的解析器的API都存在于org.json包下,用到的類有下面這寫:

          • JSONObject: Json對象,可以完成Json字符串與Java對象的相互轉換
          • JSONArray: Json數(shù)組,可以完成Json字符串與Java集合或對象的相互轉換,[]
          • JSONStringer: Json文本構建類,這個類可以幫助快速和便捷的創(chuàng)建JSON text, 每個JSONStringer實體只能對應創(chuàng)建一個JSON text
          • JSONTokener:Json解析類
          • JSONException:Json異常

          使用方法參見案例17的原生解析方法,如下:

          private List<Lesson> parseJsonByNative(String jsonStr) {
            List<Lesson> lessons=new ArrayList<>();
            try {
              JSONObject jsonObject=new JSONObject(jsonStr);
              int code=jsonObject.getInt("status");
              if (code !=1) {
                return null;
              }
              JSONArray dataArray=jsonObject.getJSONArray("data");
              for (int i=0; i < dataArray.length(); i++) {
                JSONObject lessonObject=dataArray.getJSONObject(i);
                int id=lessonObject.getInt("id");
                String name=lessonObject.getString("name");
                String picSmall=lessonObject.getString("picSmall");
                String picBig=lessonObject.getString("picBig");
                String description=lessonObject.getString("description");
                int learner=lessonObject.getInt("learner");
          
                Lesson lesson=new Lesson();
                lesson.setId(id);
                lesson.setName(name);
                lesson.setPicSmall(picSmall);
                lesson.setPicBig(picBig);
                lesson.setDescription(description);
                lesson.setLearner(learner);
          ?
                lessons.add(lesson);
              }
            } catch (JSONException e) {
              e.printStackTrace();
            }
            return lessons;
          }

          1.2 Gson解析庫

          Gson是google開源的一款用于json解析的庫,受到很多開發(fā)者的喜愛。

          Gson在github的開源庫地址:https://github.com/google/gson

          在Android中使用gson有兩種方式:

          • 在build.gradle文件中設置庫依賴:implementation 'com.google.code.gson:gson:2.8.6'
          • 下載gson.jar包,放在Android項目惡libs目錄中

          設置依賴后,即可在項目中使用Gson解析數(shù)據(jù),如下所示:

          private Lesson[] parseByGson(String jsonStr) {
            Gson gson=new Gson();
            Type type=new TypeToken<Common<Lesson>>() {
            }.getType();
            Common<Lesson> common=gson.fromJson(jsonStr, type);
            return common.data;
          }

          1.3 FastJson解析庫

          fastjson是阿里巴巴團隊開源的一款json解析庫,使用的項目和團隊也很多。在github上的star數(shù)達到了21.2k,超過了gson。

          FastJson在復雜類型的Bean轉換Json上會出現(xiàn)一些問題,可能會出現(xiàn)引用的類型,導致Json轉換出錯,需要制定引用。FastJson采用獨創(chuàng)的算法,將parse的速度提升到極致,超過所有json庫。

          fastjson開源庫在github的開源地址:https://github.com/alibaba/fastjson

          在Android中使用fastjson,需要在項目的build.gradle文件中設置依賴:

          compile 'com.alibaba:fastjson:1.1.71.android'

          同樣的和gson一樣,也可以下載最新的jar文件,放在android項目的libs目錄中進行依賴設置。

          public static List<Lesson> parseByFastJson(String jsonStr) {
            com.alibaba.fastjson.JSONObject jsonObject=JSON.parseObject(jsonStr);
            com.alibaba.fastjson.JSONArray jsonArray=jsonObject.getJSONArray("data");
            return  jsonArray.toJavaList(Lesson.class);
          }

          1.4 Jackson

          Jackson是當前用的比較廣泛的,用來序列化和反序列化json的Java開源框架。Jackson是最流行的json解析器之一,Java應用框架中很多都是使用Jackson庫。目前github上Jackson的star數(shù)量達到5.5K。

          Jackson在github上的地址如下:https://github.com/FasterXML/jackson

          使用Jackson:

          • 先下載jar包
          • 放入到項目的libs目錄中,設置依賴為library
          • 在x項目中進行使用

          此處省略案例,可自行練習。

          1.5 解析庫對比和總結

          • 反序列化操作:總體上JSONObject處理性能比較突出,但是JSONObject的缺點是啰嗦,代碼量多,需要些try...catch等冗余代碼。
          • Gson:隨著數(shù)據(jù)量的增大,Gson庫耗時會增加。
          • FastJson操作:性能比較好,數(shù)據(jù)的量級對內存消耗影響較小,且消耗內存比較小。
          • JSONObject原生:數(shù)據(jù)量大時,JSONObject內存消耗很明顯。
          • Jackson:耗時和內存消耗上都較大。

          ① 數(shù)據(jù)量小時,可以選擇JSONObject進行處理,要接收代碼量冗余。Gson和FastJson差不多。

          ② 數(shù)據(jù)量大時,或者數(shù)據(jù)量會有明顯的量級的增加變化,F(xiàn)astJson綜合表現(xiàn)更好。

          二、加載網(wǎng)絡數(shù)據(jù)的注意事項

          json數(shù)據(jù)通常都是通過網(wǎng)絡接口請求而來,因此需要進行網(wǎng)絡訪問獲取數(shù)據(jù),包括圖片的加載也是需要網(wǎng)絡的。

          uses-permission網(wǎng)絡權限

          使用網(wǎng)絡,需要在AndroidMainfest.xml文件中設置使用網(wǎng)絡權限。

          <!--網(wǎng)絡權限-->
          <uses-permission android:name="android.permission.INTERNET"/>

          Https規(guī)范

          在Android P版本開始,為了安全起見,不再允許使用http形式的接口。為了解決這個問題,可以通過在AndroidManifest.xml文件的Application文件中,設施usesCleartextTraffic屬性為true來,表示使用明文網(wǎng)絡流量。推薦還是盡快轉換接口升級為https。

          數(shù)據(jù)請求更新規(guī)范

          ① 在Android中,不能在主線程請求網(wǎng)絡,否則會報錯,網(wǎng)絡請求需要放在工作子線程中。

          ② 在Android中,請求數(shù)據(jù)完畢,不能在子線程中操作UI,否則會報錯。

          圖片加載開源庫

          圖片加載在android中可以使用比較成熟的開源庫來解決,常用的圖片加載開源庫是Glide,picasso等。

          glide

          glide在github上的開源地址是:https://github.com/bumptech/glide

          使用時首先需要引入glide庫的依賴:

          //圖片網(wǎng)絡庫
          implementation 'com.github.bumptech.glide:glide:4.11.0'
          annotationProcessor 'com.github.bumptech.glide:compiler:4.11.0'

          在圖片控件加載的地方,執(zhí)行如下操作:

           Glide.with(mContext).load(lesson.getPicBig()).into(holder.imgCover);

          picasso

          picasso在github上的開源地址是:https://github.com/square/picasso

          使用時首先需要引入glide庫的依賴:

          implementation 'com.squareup.picasso:picasso:2.71828'

          在圖片控件加載的地方,執(zhí)行如下操作:

          Picasso.get().load("http://i.imgur.com/DvpvklR.png").into(imageView);

          三、Android常見的網(wǎng)絡請求

          3.1 HttpURLConnection

          與java的基礎相同,HttpURLConnection可以實現(xiàn)網(wǎng)絡請求。具體步驟為:

          • 構建URL。
          • openConnection打開HttpURLConnection對象。
          • 通過IO流讀取數(shù)據(jù)。

          3.2 Volley庫

          在Goole I/O 2013上發(fā)布的網(wǎng)絡通信庫,取名為Volley。

          Volley的優(yōu)勢及特點是:自動調度網(wǎng)絡請求、支持請求優(yōu)先級、支持取消請求,可以取消單個請求或多個,并且Volley回調時候是在主線程,可以直接操作UI。

          Volley庫的操作和使用說明文檔,可以訪問如下地址:https://developer.android.com/training/volley/index.html

          設置庫依賴

          implementation 'com.android.volley:volley:1.1.1'

          RequestQueue請求列隊

          請求之前,首先需要構建RequestQueue請求列隊,全局也只初始化一次就好。

          Request請求對象

          Request請求對象,有StringRequest、ImageRequest、ClearCacheRequest、JsonRequest這四個子類。

          可以給Request設置一個tag,并通過RequestQueue.cancelAll(tag)可以進行取消。

          3.3 Okhttp

          第二種方式是使用成熟的網(wǎng)絡請求庫,比如說Okhttp,非常火的一個網(wǎng)絡庫,由Square公司提供。

          Okhttp開源庫的github地址如下:https://github.com/square/okhttp

          最新的Okhttp庫的版本是4.6.0,在Android應用中使用該庫的操作方法是設置庫依賴,在build.gradle文件中:

          implementation("com.squareup.okhttp3:okhttp:4.6.0")

          3.3.1 使用步驟

          • 構建OkHttpClient對象:全局只需要初始化一次即可。
          • Request對象:通過Builder進行構建和參數(shù)設置。
          • 請求:get請求直接使用.get();post請求通過.post(RequestBody),攜帶數(shù)據(jù)。
          OkHttpClient client=new OkHttpClient();
          
          String run(String url) throws IOException {
            Request request=new Request.Builder()
                .url(url)
                .build();
            try (Response response=client.newCall(request).execute()) {
              return response.body().string();
            }
          }

          OkHttp庫的請求,回調方法是運行在子線程中,因此不能直接在回調函數(shù)更新ui操作,如果在子線程中操作UI,刷新界面操作,會報如下錯誤:

          Only the original thread that created a view hierarchy can touch its views

          如果出現(xiàn)該錯誤,可以使用如下的方法解決。該方法用于回到主線程操作UI:

          面已經(jīng)介紹了HttpServletResponse響應對象中的一些常用方法,這一小節(jié)介紹如何使用HttpServletResponse響應對象,將結果返回給瀏覽器客戶端。

          1.1、返回HTML內容

          使用Servlet返回HTML內容給客戶端,是一個比較常見的功能,因為Servlet本來就是用于JavaWeb開發(fā)的,而HTML就是Web開發(fā)的三大核心語言之一。這里給出一個響應HTML內容給客戶端的案例代碼:

          package com.gitcode.servlet;
          
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;
          import java.io.PrintWriter;
          
          /**
           * @version 1.0.0
           * @Date: 2024/2/10 20:20
           * @Author ZhuYouBin
           * @Description:
           */
          public class HtmlResponseServlet extends HttpServlet {
              @Override
              protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  // 響應HTML內容
                  response.setContentType("text/html;charset=UTF-8");
                  // 獲取輸出流
                  PrintWriter writer=response.getWriter();
          
                  // 輸出HTML內容
                  writer.println("<!DOCTYPE html>");
                  writer.println("<html lang=\"en\">");
                  writer.println("<head>");
                  writer.println("    <meta charset=\"UTF-8\">");
                  writer.println("    <title>響應HTML內容</title>");
                  writer.println("</head>");
                  writer.println("<body>");
                  writer.println("    <h3>Hello World!你好,世界!</h3>");
                  writer.println("</body>");
                  writer.println("</html>");
          
                  // 關閉流
                  writer.close();
              }
          }

          運行結果如下所示:

          1.2、返回JSON內容

          JSON格式在實際的Web開發(fā)中,可以說是最常用的數(shù)據(jù)交互格式啦,在一些前后端分離的項目中,都是采用JSON來進行數(shù)據(jù)交互的,所以這里給出一個響應JSON內容的案例代碼:

          package com.gitcode.servlet;
          
          import javax.servlet.ServletException;
          import javax.servlet.http.HttpServlet;
          import javax.servlet.http.HttpServletRequest;
          import javax.servlet.http.HttpServletResponse;
          import java.io.IOException;
          import java.io.PrintWriter;
          
          /**
           * @version 1.0.0
           * @Date: 2024/2/10 20:20
           * @Author ZhuYouBin
           * @Description:
           */
          public class JsonResponseServlet extends HttpServlet {
              @Override
              protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
                  // 響應JSON內容
                  response.setContentType("application/json;charset=UTF-8");
                  // 獲取輸出流
                  PrintWriter writer=response.getWriter();
          
                  // 輸出JSON內容
                  writer.println("{");
                  writer.println(" \"username\":\"名字是Tom-2024\",");
                  writer.println(" \"password\":\"123456\"");
                  writer.println("}");
          
                  // 關閉流
                  writer.close();
              }
          }

          運行結果如下所示:

          以上,就是使用HttpServletResponse對象返回HTML和JSON數(shù)據(jù)格式。

          今天就到這里,未完待續(xù)~~

          家好,我是Python進階者。

          背景介紹

          我們知道再爬蟲的過程中我們對于爬取到的網(wǎng)頁數(shù)據(jù)需要進行解析,因為大多數(shù)數(shù)據(jù)是不需要的,所以我們需要進行數(shù)據(jù)解析,常用的數(shù)據(jù)解析方式有正則表達式,xpath,bs4,這次我們來介紹一下另一個數(shù)據(jù)解析庫--jsonpath,在此之前我們需要先了解一下什么是json。


          一、初識Json

          JSON(JavaScript Object Notation) 是一種輕量級的數(shù)據(jù)交換格式,它使得人們很容易的進行閱讀和編寫。同時也方便了機器進行解析和生成。適用于進行數(shù)據(jù)交互的場景,比如網(wǎng)站前臺與后臺之間的數(shù)據(jù)交互。


          Python 2.7及之后版本,自帶了JSON模塊,直接import json就可以使用了。

          官方文檔:http://docs.python.org/library/json.html

          Json在線解析網(wǎng)站:http://www.json.cn/#


          二、Json的基本使用

          簡介

          json簡單說就是javascript中的對象和數(shù)組,所以這兩種結構就是對象和數(shù)組兩種結構,通過這兩種結構可以表示各種復雜的結構;

          1. 對象:對象在js中表示為{ }括起來的內容,數(shù)據(jù)結構為 { key:value, key:value, ... }的鍵值對的結構,在面向對象的語言中,key為對象的屬性,value為對應的屬性值,所以很容易理解,取值方法為 對象.key 獲取屬性值,這個屬性值的類型可以是數(shù)字、字符串、數(shù)組、對象這幾種。
          2. 數(shù)組:數(shù)組在js中是中括號[ ]括起來的內容,數(shù)據(jù)結構為 ["Python", "javascript", "C++", ...],取值方式和所有語言中一樣,使用索引獲取,字段值的類型可以是 數(shù)字、字符串、數(shù)組、對象幾種。


          使用

          json模塊提供了四個功能:dumpsdumploadsload,用于字符串 和 python數(shù)據(jù)類型間進行轉換。

          把Json格式字符串解碼轉換成Python對象 從json到python的類型轉化對照如下:

          JSON

          Python

          object

          dict

          array

          list

          string

          unicode

          number(int)

          int,long

          number(real)

          float

          true(false)

          True(False)

          null

          None


          1.json.loads()

          import json
          
          
          strDict='{"city": "廣州", "name": "小黑"}'
          
          
          r=json.loads(strDict) # json數(shù)據(jù)自動按Unicode存儲
          
          
          print(r)

          結果如下:

          {'city': '廣州', 'name': '小黑'}


          2. json.load()

          讀取文件中json形式的字符串元素 轉化成python類型

          import json
          s=json.load(open('test.json','r',encoding='utf-8'))
          print(s,type(s))

          結果如下:

          {'city': '廣州', 'name': '小黑'} <class 'dict'>


          3. json.dumps()

          實現(xiàn)python類型轉化為json字符串,返回一個str對象 把一個Python對象編碼轉換成Json字符串

          import json
          
          
          listStr=[1, 2, 3, 4]
          dictStr={"city": "北京", "name": "大貓"}
          
          
          s1=json.dumps(listStr)
          s2=json.dumps(dictStr,ensure_ascii=False)
          
          
          print(s1,type(s1))
          print(s2)

          結果如下:

          [1, 2, 3, 4] <class 'str'>{"city": "北京", "name": "大貓"} <class 'str'>

          注意:

          1. json.dumps() 序列化時默認使用的ascii編碼
          2. 添加參數(shù) ensure_ascii=False 禁用ascii編碼,按utf-8編碼


          4. json.dump()

          將Python內置類型序列化為json對象后寫入文件

          import json
          
          
          json_info="{'age': '12'}"
          file=open('ceshi.json','w',encoding='utf-8')
          json.dump(json_info,file)

          結果如下:

          ceshii,json(目錄文件產(chǎn)生)



          三、JsonPath

          JsonPath 是一種信息抽取類庫,是從JSON文檔中抽取指定信息的工具,提供多種語言實現(xiàn)版本,包括:Javascript, Python, PHP 和 Java。

          JsonPath 對于 JSON 來說,相當于 XPATH 對于 XML。

          下載地址:https://pypi.python.org/pypi/jsonpath

          安裝方法:點擊Download URL鏈接下載jsonpath,解壓之后執(zhí)行python setup.py install

          官方文檔:http://goessner.net/articles/JsonPath


          JsonPath與XPath語法對比

          Json結構清晰,可讀性高,復雜度低,非常容易匹配,下表中對應了XPath的用法。

          XPath

          JSONPath

          描述

          /

          $

          根節(jié)點

          .

          @

          現(xiàn)行節(jié)點

          /

          .or[]

          取子節(jié)點

          ..

          n/a

          取父節(jié)點,Jsonpath未支持

          //

          ..

          就是不管位置,選擇所有符合條件的條件

          *

          *

          匹配所有元素節(jié)點

          @

          n/a

          根據(jù)屬性訪問,Json不支持,因為Json是個Key-value遞歸結構,不需要。

          []

          []

          迭代器表示(可以在里邊做簡單的迭代操作,如數(shù)組下標,根據(jù)內容選值等)

          |

          [,]

          支持迭代器中做多選。

          []

          ?()

          支持過濾操作.

          n/a

          ()

          支持表達式計算

          ()

          n/a

          分組,JsonPath不支持


          四、案例測試

          我們爬取淘票票官網(wǎng)的城市信息,保存為json文件,進行jsonpath語法測試,獲取所有城市名稱。

          請求

          import requests
          import time
          
          
          url='https://dianying.taobao.com/cityAction.json?activityId&_ksTS=1632211792156_137&jsoncallback=jsonp138&action=cityAction&n_s=new&event_submit_doGetAllRegion=true'
          
          
          headers={
              'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.106 Safari/537.36',
          } 
          
          
          res=requests.get(url,headers=headers)
          
          
          result=res.content.decode('utf-8')
          
          
          print(result) # xxx省略

          注意:

          headers里面的鍵值對最好都加上,還是有反爬的,該網(wǎng)站,這里為了簡便省去了;


          保存數(shù)據(jù)

          content=result.split('(')[1].split(')')[0] # 由于文件首尾的字符不需要需要剔除掉做字符串切割
          
          
          with open('tpp.json','w',encoding='utf-8')as fp:
              fp.write(content)

          打開json文件如下所示:


          解析數(shù)據(jù)

          這里我們獲取全部城市名稱

          import json
          import jsonpath
          
          
          obj=json.load(open('tpp.json','r',encoding='utf-8')) # 注意,這里是文件的形式,不能直接放一個文件名的字符串
          
          
          city_list=jsonpath.jsonpath(obj,'$..regionName') # 文件對象   jsonpath語法
          
          
          print(city_list)

          結果如下:


          五、總結

          我們知道json是一種常見的數(shù)據(jù)傳輸形式,所以對于爬取數(shù)據(jù)的數(shù)據(jù)解析,json的相關操作是比較重要的,能夠加快我們的數(shù)據(jù)提取效率,本文簡單介紹了json和jsonpath的相關操作,對于測試網(wǎng)站(淘票票)的json做了簡單的數(shù)據(jù)解析,感興趣的小伙伴可以把其他數(shù)據(jù)解析一下。


          主站蜘蛛池模板: 国产乱人伦精品一区二区| 亚洲AV无码一区二区三区在线 | 亚洲色婷婷一区二区三区| 韩国福利一区二区三区高清视频| 亚洲国产精品成人一区| 国产99精品一区二区三区免费 | 性色av闺蜜一区二区三区| 亚洲AV永久无码精品一区二区国产| 性色AV一区二区三区无码| 中文字幕在线视频一区| 91一区二区视频| 国产成人精品一区二区三区无码| 中文字幕无码不卡一区二区三区 | 中文字幕一区二区精品区| 精品人妻少妇一区二区| 人妻互换精品一区二区| 人妻少妇精品视频一区二区三区| 国产伦精品一区二区三区视频小说 | 精品无码国产一区二区三区AV | 亚洲国产国产综合一区首页| 波多野结衣一区二区| 国产一区二区三区在线| 亚洲AV无码一区二区三区系列| 国内精品视频一区二区三区八戒| 国产免费无码一区二区| 国产成人久久一区二区三区 | 亚洲视频在线一区| 国产av福利一区二区三巨| 亚洲欧洲专线一区| 性色AV一区二区三区| 色精品一区二区三区| 亚洲天堂一区在线| 国产福利电影一区二区三区,免费久久久久久久精 | 久久久精品人妻一区二区三区| 亚洲国产成人久久一区WWW| 日韩精品一区二区午夜成人版 | 国产一区二区三区精品久久呦 | 国产免费一区二区三区VR| 无码人妻一区二区三区免费手机| 日韩AV无码久久一区二区| 国产一区二区免费|