2.2 使用Python獲取運營數據-2
說明:本文是《Python數據分析與數據化運營》中的「2.2 使用Python獲取運營數據」中的第二部分,由於本節內容較多,這裡分幾個文章。
-----------------------------下面是正文內容--------------------------
2.2.2 從Excel獲取運營數據
現有的Excel分為兩種格式:xls(Excel 97-2003)和xlsx(Excel 2007及以上)。Python處理Excel文件主要是第三方模塊庫xlrd、xlwt、pyexcel-xls、xluntils和pyExcelerator,以及win32com和openpyxl模塊,此外Pandas中也帶有可以讀取Excel文件的模塊(read_excel)。
基於擴展知識的目的,我們使用xlrd模塊讀取Excel數據。
首先安裝該庫,在系統終端命令行輸入命令pip install xlrd。
然後我們以「附件-chapter2」文件夾demo.xlsx數據文件為例,介紹該庫的具體應用。數據概覽如圖2-7所示:
圖2-7 數據文件內容
import xlrd # 導入庫# 打開文件xlsx = xlrd.open_workbook(demo.xlsx)# 查看所有sheet列表print (All sheets: %s %xlsx.sheet_names())print(===================================) # 內容分割線# 查看sheet1的數據概況sheet1 = xlsx.sheets()[0] # 獲得第一張sheet,索引從0開始sheet1_name = sheet1.name # 獲得名稱sheet1_cols = sheet1.ncols # 獲得列數sheet1_nrows = sheet1.nrows # 獲得行數print (Sheet1 Name: %s
Sheet1 cols:%s
Sheet1 rows: %s) % (sheet1_name, sheet1_cols, sheet1_nrows)print (===================================) # 內容分割線# 查看sheet1的特定切片數據sheet1_nrows4 = sheet1.row_values(4) # 獲得第4行數據sheet1_cols2 = sheet1.col_values(2) # 獲得第2列數據cell23 = sheet1.row(2)[3].value # 查看第3行第4列數據print (Row 4: %s
Col 2: %s
Cell 1: %s
% (sheet1_nrows4, sheet1_cols2, cell23))print(===================================) # 內容分割線# 查看sheet1的數據明細for i in range(sheet1_nrows): # 逐行列印sheet1數據print (sheet1.row_values(i))
上述代碼中,我們先讀取一個Excel文件,再查看所有sheet(工作簿)並輸出sheet1相關屬性信息;然後查看sheet1中特定數據行、列和元素的信息;最後我們用循環的方式,依次讀取每個數據行並列印輸出。
以下是代碼執行後列印輸出的結果:
All sheets: [uSheet1]===================================Sheet1 Name: Sheet1Sheet1 cols: 4Sheet1 rows: 10===================================Row 4: [u431381197408191515,uu6709u6548, 42725.0, uu6df1u5733u5e02]Col 2: [uCreate_Time, 42725.0, 42725.0,42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0]Cell 1: 深圳市===================================[uID_number, uStatus, uCreate_Time,uBusiness_City][u431381198109106573, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381198809122734, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381197903117478, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381197408191515, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381197606166011, uu6709u6548,42725.0, uu6df1u5733u5e02][u43138119850623339X, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381198908223477, uu6709u6548,42725.0, uu6df1u5733u5e02][u431381198901176911, uu6709u6548,42725.0, uu6df1u5733u5e02][u43138119870827275X, uu6709u6548,42725.0, uu6df1u5733u5e02]
提示 在上述列印輸出的內容中,我們發現第二列、第三列、第四列與原始數據似乎不同。第二列和第四列「異常」的原因是將中文編碼統一轉換為Unicode編碼,便於在不同程序間調用;第三列「異常」是由於將日期格式轉換為數值格式而已。
上述操作只是將數據從Excel中讀取出來,基於讀取的數據轉換為數組便可以進行矩陣計算。由於矩陣計算大多是基於數值型數據實現的,因此上述數據將無法適用於大多數科學計算場景,這點需要注意。
總結:在企業實際場景中,由於Excel本身的限制和適用,其無法存儲和計算過大(例如千萬級的數據記錄)的數據量,並且Excel本身也不是為了海量數據的應用而產生的。因此,Excel可以作為日常基本數據處理、補充數據來源或者匯總級別的數據進行讀取,同時也可以作為數據結果展示的載體,這種應用下對於大量數值表格的應用效果非常好。
2.2.3 從關係型資料庫MySQL讀取運營數據
在第一章「1.2.4 資料庫和客戶端」中我們介紹了安裝MySQL和Navicat的方法和關鍵步驟。這裡我們介紹如何從利用Python從MySQL中讀取數據。
在「附件-chapter2」文件夾中有一個名為order.xlsx的數據文件,我們先把文件導入MySQL資料庫,然後再基於資料庫進行相關操作。
第一步,新建一個資料庫用於存放要導入的目標數據。
步驟1 打開Navicat,左側導航欄中有我們已經建立好的資料庫鏈接,在第一章中我們已經建立好了本地連接,名為「127.0.0.1」。
步驟2 雙擊該資料庫連接,會展示出所有當前連接(對應的用戶許可權)下可用的資料庫,如圖2-8。
圖2-8 127.0.0.1下的資料庫
步驟3 為了保持不同數據的獨立性,我們新建一個資料庫,單獨存放特定主題的數據。在「127.0.0.1」名稱上右鍵,在彈出的菜單中選擇新建資料庫,然後做如下設置並點擊確定。完成之後在左側的「127.0.0.1」鏈接下會新增一個剛才新建的資料庫「python_data」。
第二步,將Excel數據導入資料庫。
雙擊剛才新建的名為「python_data」的資料庫名稱,激活資料庫連接。此時右側功能欄中的部分功能已經可用。點擊「導入嚮導」,開始導出Excel數據。如圖2-10。
圖2-10 創建導入嚮導
步驟1 選擇數據文件格式:Excel 2007
步驟2 選擇數據源文件。
圖2-11 設置導入數據源
步驟3 定義附加選項。由於數據文件中第一行是表頭,因此數據從第二行開始;日期分隔符與數據文件一致,需要設置為「-」,其他都為默認值。
圖2-12 設置導入附件選項
步驟4 設置目標數據表名為order。
步驟5 設置欄位類型、長度、約束等信息。其中主要的設置是將order_data類型設置為date(日期型),長度為0(不做限制);order_tme類型設置為time(時間型),長度為0(不做限制);total_amount類型設置為float(浮點型),長度默認為255。
圖2-13 設置欄位類型等約束
提示 實際上,我們的數據很可能用不了那麼多的「存儲空間」,因此在設置時存在數據空間冗餘,不過沒關係,這裡我們僅僅做入門引導之用。真正涉及到資料庫表的模型設計有很多學問,這裡的設置不會影響我們做數據統計分析之用。
步驟6 設置導入模式。由於我們是新創建表,因此設置為: 添加
步驟7 啟動導入任務。點擊 開始 即可。
等待系統導入數據,導入成功後,會在窗口中顯示如下信息,最終的信息中包含「successfully」,如圖2-14。點擊關閉按鈕即可。
圖2-14 導入成功提示信息
至此我們已經成功導入數據,在資料庫python_data下新增了一個名為「order」的數據表。我們要初步驗證導入的數據是否與原始數據一致。雙擊打開該表 。
打開表之後,會彈出信息提示該表沒有主鍵。該信息不影響我們使用該表,點擊確定即可。
圖2-15 提示表沒有主鍵
提示 在創建表時,我們完全可以指定主鍵,例如本案例中的order_id是唯一的,那麼可指定該欄位作為主鍵,更可以創建一個自增長ID作為主鍵。本節的主要內容是介紹如何導入外部數據到資料庫,有關資料庫建表還有很多話題,在此不作更多介紹。
打開order表之後,會顯示如下表預覽內容:
圖2-16數據表概覽
在當前窗口,點擊「文件-查詢表」或直接使用快捷鍵Ctrl+Q,打開SQL窗口,然後輸入SELECT * FROM `order` LIMIT 5;點擊「運行」或使用快捷鍵Ctrl+R,返回前5條結果,如下圖2-17。讀者可以在此輸入其他SQL或直接瀏覽數據表來核對數據導入是否準確。
注意 由於表名order是資料庫中的排序關鍵字,因此在查詢表時需要寫為`order`,否則會報錯。
圖2-17運行SQL並返回結果
導入Excel數據主要核對的信息點包括:
- 數據記錄數是否一致:使用SELECTCOUNT(*) FROM `order`;或在導入成功提示窗口也可以看到)
- 數據欄位數量是否一致,導入表中的欄位不能多也不能少
- 查看數據內容是否一致,尤其是日期、時間等非字元串欄位的數據,很多時候時間型的數據轉換會出現0000-00-00,這通常是導入設置的日期分隔符問題
- 數據精準度是否一致,尤其是原始數據是浮點型,對應到資料庫欄位是否還是浮點型(注意小數位數),問題通常出現在欄位類型和位數設置
- 注意欄位的最大長度,不同的數值型數據長度位數是不同,例如整數型tinyint、int,浮點型的單精度和雙精度浮點等,這對於匯總級別的數據會產生極大影響(因為某些欄位的匯總數據可能非常大)。
通過Python連接MySQL需要有Python庫來建立連接,本節使用MySQL官方驅動連接程序,更多信息可在「1.2.3 Python第三方庫」中的「5. 資料庫連接庫」中找到。
以下是Python讀取資料庫數據的基本方法:
import mysql.connector # 導入庫config = {host: 127.0.0.1, # 默認127.0.0.1user: root, # 用戶名password: 123456, # 密碼port: 3306, # 埠,默認為3306database: python_data, # 資料庫名稱charset: gb2312 # 字元編碼}cnn = mysql.connector.connect(**config) # 建立mysql連接cursor = cnn.cursor() # 獲得游標sql = "SELECT * FROM `order`" # SQL語句cursor.execute(sql) # 執行sql語句data = cursor.fetchall() # 通過fetchall方法獲得數據for i in data[:2]: # 列印輸出前2條數據print(i)cursor.close() # 關閉游標cnn.close() # 關閉連接
上述代碼中,實現了通過Python連接MySQL查詢所有的數據,並輸出前2條數據的功能。執行結果如下:
(u3897894579, datetime.date(2010, 3, 11),datetime.timedelta(0), uPENDING_ORDER_CONFIRM, u1038166, 59.0)(u3897983041, datetime.date(2010, 3, 11),datetime.timedelta(0), uREMOVED, u1041656, 19.9)
在應用MySQL中,除了查詢所有數據外,更多時候我們還會應用更多SQL技巧來幫助我們快速找到目標數據並作初步處理。以下是常用SQL語法。
只查詢前N條數據而非全部數據行記錄。示例:只查詢前100條數據記錄。
SELECT * FROM `order` LIMIT 100;
知識點:LIMIT為限制的數據記錄數方法,語法為limit m, n,意思是從第m到m+n條數據。m可省略,默認值從0開始,如上述示例中是從0開始,取100條數據。例如,要從第11條開始取,取10條可以寫為SELECT * FROM `order` LIMIT 11, 10;
只查詢特定列(而非全部列)數據。示例:只查詢total_amount和order_id兩列數據。
SELECT total_amount, order_id from `order`;
知識點:選擇特定列只需將列名寫到表達式中即可,多個列名用英文逗號分隔。另外,還可以使用表名.欄位名的寫法,例如上述表達式可以寫成SELECT order.total_amount,
order.order_id from `order`;這種寫法會出現在表達式中出現多個表的情況下,例如多表關聯查詢。
查詢特定列去重後的數據。示例:查詢針對user_id去重後的數據。
SELECT DISTINCT user_id FROM `order`;
知識點:關鍵詞
DISTINCT 用於返回唯一不同的值,後面接欄位名即要去重的欄位。如果後面接多個欄位會默認對多個欄位同時進行比較,只有多個欄位完全相同時才會去重。DISTINCT常用來返回去重後的特定ID,或者與COUNT配合使用,查詢特定數據記錄的唯一數量。查詢帶有1個條件的數據。示例:查詢total_amount<100的所有數據。
SELECT * FROM `order` WHERE total_amount < 100;
知識點:WHERE是條件關鍵字,後面接具體條件。本示例中,由於total_amount為浮點型,因此直接可與數值型比較;如果是字元串型,則比較值需要加引號用來表示一致的欄位類型。
查詢帶有多個條件(同時滿足)的數據。示例:查詢total_amount<100且status為REMOVED的所有數據。
SELECT * FROM `order` WHERE total_amount < 100 and `status` = REMOVED;
知識點:多個條件使用and表示且的關係,多個條件必須同時滿足。MySQL中欄位不區分大小寫。由於status也是關鍵字,因此也需要使用`status`。
查詢帶有多個條件(滿足任意一個)的數據。示例:查詢total_amount<100或status為REMOVED的所有數據。
SELECT * FROM `order` WHERE total_amount < 100 or `status` = REMOVED;
知識點:多個條件使用or表示或的關係,多個條件滿足任意一個條件即可。
查詢特定條件值在某個值域範圍內的數據。示例:查詢status的值為REMOVED或NO_PENDING_ACTION或PENDING_ORDER_CONFIRM。
SELECT * FROM `order` WHERE `status` in (REMOVED,NO_PENDING_ACTION,PENDING_ORDER_CONFIRM);
知識點:對於特定欄位採用「窮舉法」列出值域的方法,也可以使用or方法連接多個條件,但使用列表的窮舉法會使得表達式更簡單。
使用正則表達式查詢具有複雜條件的數據。示例:查詢user_id以106開頭且order_id包含04的所有訂單數據。
SELECT * FROM `order` WHERE user_id LIKE 103% and order_id LIKE %04%;
知識點:正則表達式通常用在複雜條件中,通過使用關鍵字LIKE來連接不同的正則語法,LIKE後面接具體的匹配模式,常用的匹配模式包括:
- 以*開頭:字元串%,例如ABD%表示以ABD為開頭的所有匹配;
- 以*結尾:%字元串,例如% ABD表示以ABD為結尾的所有匹配;
- 包含*:%字元串%,例如%ABD%表示包含ABD的所有匹配。
關於正則表達式還有更多強大的語法規則,限於篇幅不作展開介紹。
將查詢到的數據倒敘排列。示例:將total_amount金額在10~100之間的所有數據,按照訂單ID倒敘排序。
SELECT * FROM `order` WHERE 10 <total_amount < 100 ORDER BY order_id DESC;
知識點:在查詢表達式ORDER
BY的結尾,通過使用DESC來表示倒敘(逆序)排序;省略是默認使用ASC正序(順序)排序。查詢指定列中不包含空值的所有數據。示例:查詢order_id不為空的所有數據。
SELECT * FROM `order` WHERE order_id IS NOT NULL;
知識點:在MySQL中,IS NULL表示為空, IS NOT NULL 表示非空。需要注意的是,NULL不代表空字元串或者空格,而是真正意義上的沒有任何數據,類似於Python中的None。
上述案例只是展示了如何取數,更多情況下,我們會配合特定函數和方法做數據計算、整合和探索性分析,例如:
- 使用MySQL聚合函數求算術平均值、計數、求最大最小值、做分類匯總等;
- 使用MySQL數學函數,用來求絕對值、對數計算、平方根等;
- 使用MySQL字元串函數進行字元串分割、組合、截取、匹配、處理等;
- 使用MySQL的日期函數進行日期獲取、轉換、處理等;
- 使用MySQL將多個表(2個或2個以上)數據進行關聯、匹配和整合。
關於在Python還是MySQL中進行數據處理計算的爭議
在Pythoner(Python工作者)看來,MySQL的很多工作Python本身也能勝任,為什麼還要耗費時間和精力學習如何在MySQL中完成這些數據工作,直接用Python讀取數據然後基於Python的相關庫進行數據運算豈不更好?
Python的工作強項並不是數據計算,而是其靈活、高效、簡易和集成多方的工作方式、效率和效果。MySQL(以及其他關係型資料庫)作為成熟的數據存儲和集成解決方案,在(關係型)數據本身方面更具優勢,尤其是對於數據結構定義(實體、屬性、關係)、關係操作(選擇、連接、聚合等)、關係完整性約束(主外鍵、唯一性等)等方面具有成熟且穩定的應用價值,這對於數據處理至關重要,因此可以說MySQL在結構化數據存儲和初步處理工作上比Python更專業。
還有一個更加關鍵的原因是如果所有數據工作都由Python完成,那麼Python的事務處理在某些情況下一定會面臨資源瓶頸、工作效率等問題,屆時可能會導致程序崩潰和報錯,這將大大降低程序的可靠性以及結果輸出的效率,對於海量數據工作尤為如此。
因此,很多時候不是Python不能做,而是在合適的時機選擇最合適的工具來完成才是最好的選擇。
2.2.4 從非關係型資料庫MongoDB讀取運營數據
由於MongoDB一般都是企業級數據存儲,因此這裡我們使用在第一章已經安裝過的SSH遠程客戶端SecureCRT。如果讀者有自己在虛擬機或本地安裝MongoDB,也可以使用,操作方法類似。
雙擊SecureCRT打開程序,點擊頂部的「快速連接」按鈕,新建連接。
圖2-18新建快速連接
然後根據伺服器具體配置情況,配置如下信息,其中主機名和用戶名需要單獨配置,其他的根據實際情況詢問IT或運維管理人員(本案例中都是默認值)。可勾選 用於以後啟動該程序時直接顯示快捷入口。
圖2-19 填寫連接配置信息
點擊連接之後,會彈出密碼輸入窗口,輸入密碼,可勾選 用於以後無需重複輸入密碼,具體視公司安全規定執行。
圖2-20 填寫密碼
如果伺服器配置信息填寫正確,連接伺服器成功會顯示如下信息:
圖2-21 成功連接伺服器
要想通過Python調用MongoDB,需要安裝PyMongoDB,直接使用pip install
pymongo即可實現。注意 不同的伺服器環境對於可訪問外網的限制有差異,有的伺服器可以訪問外網,而有的伺服器卻不能。我們在第一章中的大多數安裝方法,默認都是通過pip請求外部網路資源實現的,對於無法直接從伺服器連接外網的,請參照「1.2.3
Python第三方庫」中的方法,先將安裝包和依賴包下載到本機,然後再拷貝到伺服器上,再通過setup和pip命令安裝。
使用Python連接MongoDB之前,需要伺服器上的MongoDB處於啟動狀態。查看是否成功啟動的方法是找一個可以直接連接或訪問伺服器的瀏覽器,直接輸入IP:埠,如果出現「It
looks like you are trying to access MongoDB over HTTP on the native driverport.」字樣的提示則說明已經正常啟動和運行。例如:筆者的伺服器上已經啟動了該服務,在瀏覽器中輸入http://10.66.202.134:27017/後提示如下信息:圖2-22 MongoDB服務啟動後的瀏覽器返回信息
提示 MongoDB也提供了Windows版本的程序,有興趣的讀者,可登陸https://www.mongodb.com/download-center#community下載程序並進行本地部署安裝。
要在伺服器上進入Python環境,直接在終端窗口輸入命令python。在Python命令行窗口中,通過如下方法調用MongoDB數據。
from pymongo import MongoClient # 導入庫client = MongoClient() # 建立連接client = MongoClient(10.66.202.134,27017) # 環境變數初始化db = client.test_py # 選擇test_py庫orders = db.ordersets # 選擇orders集合terms = [{"user":"tony", "id": "31020", "age":"30", "products": ["215120", "245101","128410"], "date": "2017-04-06"},{"user": "lucy", "id": "32210","age": "29", "products": ["541001","340740", "450111"],"date": "2017-04-06"}] # 定義一條數據集合用於插入orders.insert_many(terms) # 插入數據print (orders.find_one()) # 獲取一文檔數據print(========================================)for i in orders.find(): # 獲取所有文檔數據並展示print (i)
上述代碼中,我們連接到MongoDB後選擇了test_py庫下的ordersets集合,然後插入2條數據到集合中,再從集合中查看單獨一條以及所有集合數據。
以下是代碼執行後列印輸出的結果:
{uage: u30, uproducts: [u215120,u245101, u128410], uuser: utony, udate: u2017-04-06, u_id:ObjectId(58eb1f0b2f76bf26108b4898), uid: u31020}========================================{uage: u30, uproducts: [u215120,u245101, u128410], uuser: utony, udate: u2017-04-06, u_id:ObjectId(58eb1f0b2f76bf26108b4898), uid: u31020}{uage: u29, uproducts: [u541001,u340740, u450111], uuser: ulucy, udate: u2017-04-06, u_id:ObjectId(58eb1f0b2f76bf26108b4899), uid: u32210}
除了上述基本查詢語句外,PyMongo也提供了類似於MySQL一樣的條件過濾。
查詢特定文檔數據。示例,值查詢第2條數據。
orders.find()[1] # 查詢特定索引的數據記錄
知識點:通過增加索引值可以指定查詢特定索引的文檔數據。注意索引值從0開始,0代表第一條是數據。
查詢特定範圍內的文檔數據。示例,值查詢第1-2條數據。
orders.find()[0:2] # 查詢特定範圍內的數據記錄
知識點:通過增加索引值可以指定查詢特定索引範圍的文檔數據(切片)。注意索引值為空則默認從0開始,0代表第一條是數據。上述表達式可以寫成orders.find()[:2]。索引結束值默認不包含,例如上述語法中的0:2的實際索引只有0和1。
增加查詢條件。示例:只查詢user為lucy的文檔數據。
orders.find({"user": "lucy"}) # 所有數據,注意使用迭代方法查看數據orders.find_one({"user": "lucy"}) # 單條數據
知識點:作為Key-Value形式的代表應用之一,MongoDB幾乎所有的用法都以K-V的形式存在。過濾條件也不例外,只需在find函數中,以Key-Value的形式設置過濾條件即可,其中Key為過濾維度,Value為對應值。
排序。示例:針對user排序輸出。
orders.find({"user": "lucy"}).sort("user") # 所有數據,注意使用迭代方法查看數據
知識點:通過使用Sort方法設置排序維度。默認是正序,也可以指定為倒敘排列,同時也可以指定多個欄位排序規則,例如collection.find().sort([ (field1, pymongo.ASCENDING),
(field2, pymongo.DESCENDING)])。從MongoDB 2.6開始,還提供了按照文本相關性的排序方法,例如collection.find({score: {$meta: textScore}}).sort([(score,{$meta: textScore})])。除了上述基本查詢和過濾條件外,PyMongo也提供了用於做數據統計、分析和探索的基本方法,更多信息,具體查閱http://api.mongodb.com/python/current/
總結:在企業實際應用中,非關係型資料庫往往基於「大數據」的場景產生,伴隨著海量、實時、多類型等特徵而來。這些資料庫通過捨棄了關係型資料庫的某些特徵和約束,然後在特定方面進行增強,因此才能滿足特定應用需求。非關係型資料庫由於約束性、規範性、一致性和數據準確性低於關係性資料庫,因此常用於實時海量數據讀寫、非結構化和半結構化信息讀寫、海量集群擴展、特殊場景應用等。所以在金融、保險、財務、銀行等領域內,這種應用比較少;而互聯網、移動應用等新興產業和行業領域則應用較多。
2.2.5 從API獲取運營數據
為了更好的讓所有讀者都能了解從API獲取數據的具體過程,本節使用百度免費API作為實際數據來源。百度API提供了眾多地圖類功能,可用於基本地圖、位置搜索、周邊搜索、公交駕車導航、定位服務、地理編碼及逆地理編碼等。本節使用的是百度Web服務API中的Geocoding API。
Geocoding API用於提供從地址到經緯度坐標或者從經緯度坐標到地址的轉換服務,用戶可以發送請求且接收JSON、XML的返回數據。該應用可用於對運營數據中的地址相關信息進行解析,從而獲得有關經緯度信息,這些信息可用於進一步的基於地理位置的解析、展示和分析等應用。
要獲得該API,讀者需要擁有百度相關賬戶和AK信息。
第一步 獲得百度賬戶,沒有賬戶的讀者可在https://passport.baidu.com/v2/?reg免費註冊獲取。
第二步 註冊成為百度開放平台開發者,讀者可進入http://lbsyun.baidu.com/apiconsole/key?application=key完成相關註冊。該過程非常簡單,遵循引導整個過程在5分鐘以內即可完成。
圖2-23提交成功
第三步 註冊完成之後,會有一封名為「【百度地圖開放平台】開發者激活郵件」發送驗證鏈接到指定(註冊時郵箱)郵箱,點擊鏈接進行驗證。
圖2-24激活驗證鏈接
第四步 點擊「申請秘鑰」進入創建應用界面,在該應用創建中,我們主要使用Geocoding API v2,其他應用服務根據實際需求勾選。IP白名單區域,如果不做限制,請設置為「0.0.0.0/0」。設置完成後,點擊提交。
圖2-25創建應用
第五步 獲得AK秘鑰。完成上述步驟之後,會默認跳轉到應用列表界面,界面中的「訪問應用(AK)」便是該應用的秘鑰。
圖2-26獲得AK秘鑰
1. 獲取並解析json數據
我們先通過Python請求該API來獲得json格式的數據。本示例的目標是通過給百度API發送一條地理位置數據,返回其經緯度信息。
本節會用到Python第三方庫requests,讀者需要先通過pip install requests進行安裝。完整代碼如下:
import requests # 導入庫add = 北京市中關村軟體園 # 定義地址ak =DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr # 創建訪問應用時獲得的AKurl = http://api.map.baidu.com/geocoder/v2/?address=%s&output=json&ak=%s # 請求URLres = requests.get(url % (add, ak)) # 獲得返回請求add_info = res.text # 返迴文本信息print (add_info) # 列印輸出
在上述代碼中,我們先導入一個requests庫,該庫用來發送網路請求,支持多種發送模式,可以用來做網頁內容抓取、自動化網頁測試、網頁內容採集等。
第二行我們定義了一個地址,該地址通常是運營中的地址類信息,例如:通訊地址、註冊地址、收貨地址、聯繫地址等。
第三行ak是創建訪問應用時獲得的AK,注意百度有每天6000次的限制,讀者可填寫自行申請的AK。
第四行定義了一個通過get方法發送的URL請求地址,地址中的address和ak的具體值使用佔位符代替,在後面用到時具體賦值,這種方法經常用到地址、ak有變化的場景中。例如:我們通常會創建多個應用(基於每個賬戶有限制,以及分開治理應用的考慮),然後從資料庫中讀取一系列地址用於解析,此時的地址和AK都需要能動態賦值。
提示 在API請求方法中,最常用的是get和post方法。前者用於向伺服器以「明文」(所有參數都在URL中體現)的形式請求數據,常用於普通的頁面或服務請求,例如瀏覽網頁、搜索關鍵字等都是GET方法;後者則以「暗語」(所有的數據信息都在HTTP消息中)以鍵值對的形式發送,在URL中是看不到具體信息的,常用於數據保密性高的場景,例如登錄、註冊、訂單等表單的處理都是POST方法。
第五行通過get方法發送請求到上面定義的URL中,並具體賦值。
第六行將返回對象的文本信息賦值到add_info,返回對象中還包括非常多的相關屬性信息,例如狀態碼、cookie、reason、headers、編碼等,這些信息可用於判斷是否正確返回、問題原因、狀態等信息。
最後一行列印輸出返回的文本信息。
以下是代碼執行後列印輸出的結果:
{"status":0,"result":{"location":{"lng":116.29933765654373,"lat":40.05399730253742},"precise":0,"confidence":40,"level":"工業園區"}}
返回結果包括以下欄位:
- status:返回結果狀態值, 成功返回0。
- location:經緯度坐標,其中lat是緯度值,lng是經度值。
- precise:位置的附加信息,是否精確查找。1為精確查找,即準確打點;0為不精確,即模糊打點。
- confidence:可信度,描述打點準確度。
- level:百度定義的地址類型。
該結果可以通過JSON進行格式化處理。
import json # 導入庫add_json = json.loads(add_info) # 載入Json字元串對象lat_lng =add_json[result][location] # 獲得經緯度信息print (lat_lng) # 列印輸出
代碼中,我們導入Python自帶的json庫。該庫支持Python其他對象和Json對象之間的相互轉換。
先將獲得的地址信息格式化為json字元串(字典類型),然後通過讀取字典的Key來獲得其Value,由於返回的地址信息中包含字典嵌套,因此這裡需要依次讀出第一層和第二層信息。讀者可通過add_json.items()來更加直觀的觀察2層嵌套。
上述代碼執行後,返回的結果(字典類型)可進行進一步處理:
{ulat: 40.05399730253742, ulng:116.29933765654373}
2. 獲取並解析xml數據
Geocoding API也提供XML格式的返回數據,下面以獲得XML格式的數據為例介紹代碼過程。
import requests # 導入庫add = 北京市中關村軟體園 # 定義地址ak =DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr # 創建訪問應用時獲得的AKurl =http://api.map.baidu.com/geocoder/v2/?address=%s&output=xml&ak=%s # 請求URLres = requests.get(url % (add, ak)) # 獲得返回請求add_info = res.text # 返迴文本信息print (add_info) # 列印輸出
上述所有代碼與json格式的代碼完全相同,只在第四行定義url時,將output的返回值類型設置為xml,執行後返回結果如下:
<?xml version="1.0"encoding="utf-8"?><GeocoderSearchResponse><status>0</status><result><location><lng>116.299337657</lng><lat>40.0539973025</lat></location><precise>0</precise><confidence>40</confidence><level>工業園區</level></result></GeocoderSearchResponse>接著我們通過引入一個xml格式化處理庫來從中提取經緯度信息。關於xml文件的解析,Python默認和第三方的常用庫包括xml、libxml2、lxml、xpath等,我們使用Python自帶的xml進行處理。# 設置字元編碼為utf-8import sysreload(sys)sys.setdefaultencoding(utf-8)import xml.etree.ElementTree as Etree # 導入xml中的ElementTree方法root = Etree.fromstring(add_info) # 獲得xml的根節點lng = root[1][0][0].text # 獲得lng數據lat = root[1][0][1].text # 獲得lat數據print (lng: %s % lng) # 格式化列印輸出print (lat: %s % lat) # 格式化列印輸出
上述代碼中,前4行實現了一個功能,將代碼的字元編碼設置為utf-8,否則系統會默認為ASCII,對返回的帶有中文字元串無法識別而報錯。
代碼第五行導入XML自帶的ElementTree方法,該方法可以實現對XML內容的查詢、新建、修改等操作,是XML中比較簡單容易上手的方法(XML除了ElementTree外,還提供了DOM和SAX方法)。
代碼第六行獲得從API得到的XML對象並獲得根節點。
代碼第七、八行分別通過嵌套讀取從根節點開始向下的第3層經緯度數據。
代碼最後兩行格式化列印輸出
上述代碼執行後返回結果如下:
lng: 116.299337657lat: 40.0539973025
有關百度API的更多信息,具體查閱http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
總結:在API應用中,中文的編碼處理常常是非常頭疼的細節。因此,如果可以盡量少的直接在API的數據中出現中文字元。在實際企業應用中,會出現多種API形式,但無論哪種形式,其基本實現思路都是一致的:導入庫→定義請求變數→發送請求→獲得返回數據→格式化並獲得目標數據,因此需要掌握Json和xml的數據與其他數據的轉換方法。
推薦閱讀:
※霍金已逝,這些物理學家也慢慢被淡忘了
※票房數據脫水後,到底誰在裸泳?
※票房預測那些事兒
※厲兵秣馬 砥礪前行
TAG:Python數據分析書籍 | 數據分析 | 數據化運營 |