第2章 資料化營運的資料來源
“巧婦難為無米之炊”,對于資料工作者來說資料便是所有工作的基礎。企業的資料化營運的資料來源複雜,從資料結構類型看,包括結構化和非結構化資料;從資料來源看,既有導出的資料檔案、資料庫等常見來源,又有流式資料、API等複雜系統接口和外部資源;從資料格式來看,有普通文本、視訊格式、音頻格式等。
本章将從資料類型和資料來源兩個方面介紹資料化營運的資料來源,在第3部分我們還會簡單介紹有關讀取非結構化資料集的知識,包括網頁抓取資料、文本、圖像、視訊、語音等,用來進行資料化的整體資料資源的整合。
2.1 資料化營運的資料來源類型
資料化營運的資料來源類型包括資料檔案、資料庫、API、流式資料、外部公開資料和其他來源等。
2.1.1 資料檔案
資料檔案就是存儲資料的檔案,廣義上,任何檔案中存儲的資訊都可以稱為資料;狹義上,資料檔案中是以數字或文本形式存儲的結構化的資料記錄,本節的範圍指的是後者。
結構化資料檔案大多來源于資料庫,例如,從MySQL中導出2017年1月4日到2017年10月21日的訂單明細資料并存儲為csv檔案;也有系統或工具的工作過程或傳回結果,例如,Windows版本的Tesseract文字識别後的結果會存儲到txt文本檔案中。
資料檔案常見的資料格式類型既包括txt、csv、tsv、xls、xlsx等正常格式,也包括xml、html、doc、sql等非正常資料格式。檔案格式取決于資料處理需求,也受限于來源系統的導出格式。如圖2-1所示為使用Navicat 9.0.10連接配接MySQL 5.7.21支援導出的資料格式。

大多數情況下,txt(任意指定分隔符)、csv(以逗号分隔的資料檔案)、tsv(以Tab制表符分隔的資料檔案)是最常用的資料檔案格式。不同的工具對于檔案打開的性能支援有差異,在檢視資料時,當資料檔案大小在百兆級别以下時,可以使用Excel等工具打開;資料檔案大小在百兆級别時,推薦使用Notepad打開;當資料檔案大小在G級别時,推薦使用UltraEdit打開。
2.1.2 資料庫
資料庫(DataBase)是按照資料結構來組織、存儲和管理資料的倉庫。資料庫廣泛應用于CMS(内容管理系統)、CRM(客戶關系管理系統)、OA(辦公自動化)、ERP(企業資源計劃)、财務系統、DSS(決策支援系統)、資料倉庫和資料集市、進銷存管理、生産管理、倉儲管理等各類企業營運事務之中。
資料庫的主要應用包括資料的定義、存儲、增加、删除、更新、查詢等事務型工作,資料傳輸、同步、抽取、轉換、加載等資料清洗工作,資料計算、關聯查詢、OLAP等分析型工作,以及資料權限控制、資料品質維護、異構資料庫和多系統通信互動等工作。
資料庫按類型可分為關系型資料庫和非關系型資料庫(又稱為NoSQL資料庫)。關系型資料庫在企業中非常常見,尤其在傳統企業中更為流行,常見的關系型資料庫包括DB2、Sybase、Oracle、PostgreSQL、SQL Server、MySQL等。非關系型資料庫是随着企業經營場景的多樣化以及大資料場景而出現的,根據應用場景和結構分為以下幾類。
- 面向高性能并發讀寫的鍵值(Key-Value)資料庫:優點是具有極高的并發讀寫性能,查找速度快,典型代表是Redis、Tokyo Cabinet、Voldemort。
- 面向海量文檔的文檔資料庫:優點是對資料要求不嚴格,無須提前定義和維護表結構,典型代表為MongoDB、CouchDB。
- 面向可擴充性的列式資料庫:優點是查找速度快,可擴充性強,通過分布式擴充來适應資料量的增加以及資料結構的變化,典型代表是Cassandra、HBase、Riak。
- 面向圖結構的圖形資料庫(Graph Database):優點是利用圖結構相關算法,滿足特定的資料計算需求,例如最短路徑搜尋、關系查詢等,典型代表是Neo4J、InfoGrid、Infinite Graph。
2.1.3 API
API(Application Programming Interface)是應用程式程式設計接口,在資料化營運中的API通常分為服務型API和資料型API。
服務型API可以基于預定義的規則,通過調用API實作特定功能。例如,通過調用百度地圖JavaScript API可以在網站中建構功能豐富、互動性強的地圖應用,這種API下輸入的是地理位置資料,從API獲得的輸出是可視化地圖(服務/功能)。
資料型API則通過特定的文法,通過向伺服器發送資料請求,傳回特定格式的資料(或資料檔案)。例如,通過向Google Analytics的Analytics Reporting API V4發送請求來獲得符合特定條件的資料記錄。
API廣泛應用于企業内部和外部多系統和平台互動。API傳回的資料格式,大多數情況下是JSON、XML格式。
JSON是一種輕量級的資料交換格式,由流行的JavaScript程式設計語言建立,廣泛應用于Web資料互動。JSON格式簡潔、結構清晰,使用鍵值對(Key:Value)的格式存儲資料對象。Key是資料對象的屬性,Value是資料對象屬性的對應值。例如,“性别”:“男”就是一個鍵值對結構的資料。JSON格式資料示例如下:
{
"category": {
"name": "電腦",
"brands": {
"brand": [
"DELL",
"THINKPAD"
]
}
}
}
XML是可擴充标記語言,提供了統一的方法來描述和交換獨立于應用程式或供應商的結構化資料,這是一種非常成熟且強大的資料格式。像JSON一樣,XML提供了非常好的擴充性,API的建立者可以使用它們建立自己的資料結構。XML格式資料示例如下:
<?xml version="1.0" encoding="utf-8"?>
<category>
<name>電腦</name>
<brands>
<brand>DELL</brand>
<brand>THINKPAD</brand>
</brands>
</category>
2.1.4 流式資料
流式資料指的是實時或接近實時的時效性處理的大資料流。常見的流式資料處理使用Spark、Storm和Samza等架構,能在毫秒到秒之間完成作業,用于處理應用時效性較強的場景,例如線上個性化推薦系統、網站使用者實時行為采集和分析、物聯網機器日志實時分析、金融實時消費反欺詐、實時異常人員識别等,應用領域集中在實時性較強的網際網路和移動網際網路、物聯網等。
按照資料對象來差別,流式資料可分為兩類:
第1類是使用者行為資料流。使用者行為資料流是圍繞“人”産生的資料流,包括使用者在網站和App内部因浏覽、搜尋、評論、分享、交易以及在外部的微網誌、微信中操作而産生的資料流。使用者行為資料流采集平台可分為Web站、移動站和App(包含iOS、Android、Windows等)應用。Web站及基于HTML5開發的移動應用都支援JS腳本采集,較早開發的不支援JS的Wap站(現在基本上很少)則采用NoScript方法,即一個像素的硬圖檔實作資料跟蹤。SDK是針對App提供資料采集的特定方法和架構。這3種方法可以實作目前所有線上使用者行為資料采集的需求。
第2類是機器資料流。機器資料流是圍繞“物”産生的資料流,包括從機器的生産、制造、應用、監控和管理等過程中産生的所有資料,例如機器運作日志、傳感器監控資料、音頻采集器資料、監控圖像和視訊、GPS地理資料等。
機器資料流通常集中在工業4.0、智能工廠等工業的智能營運管理過程中,也出現在物聯網、人工智能等人和物的監控、識别、聯通、互動等智能化應用中。機器資料流扮演着實時采集目标對象屬性、狀态、行為、信号等資料的角色。
2.1.5 外部公開資料
外部公開資料指公開的任意第三方都能擷取的資料。
資料化營運所需的外部公開資料來源管道衆多,常見的來源包括:
- 政府和相關機構提供的公開資料,例如國家統計局提供的月度CPI資料。
- 競争對手主動公開的資料,例如通過新聞釋出會、網絡宣傳等管道釋出的資料。
- 行業協會或相關平台組織提供的統計、資訊資料,例如艾瑞提供的行業研究報告釋出的資料。
- 第三方的組織或個人披露的與企業營運相關的資料,例如有關競争對手的供應商、客戶等資料。
2.1.6 其他來源
在某些場景下,企業資料化營運所用資料還會有其他來源,例如通過調研問卷獲得的有關産品、客戶等方面的資料,從第三方平台直接購買的資料,通過與其他廠商合作所得的互動資料等。由于這些場景比較少,并且不是企業主流的資料擷取來源,在此不過多闡述。
2.2 使用Python擷取營運資料
使用Python擷取資料,目前主要的應用方法集中在文本檔案、Excel檔案、關系型和非關系型資料庫、API、網頁等方面。本節就來介紹具體擷取方法。
2.2.1 從文本檔案讀取營運資料
1.使用read、readline、readlines讀取資料
Python可以讀取任何格式的文本資料,使用Python讀取文本資料的基本步驟如下。
(1)定義資料檔案
定義資料檔案即定義要讀取的檔案,該步驟不是必需的,可以跟“擷取檔案對象”整合。但為了後續操作的便捷性、全局資料對象的可維護性以及減少代碼備援,建議讀者養成習慣,将資料檔案預先指派給一個對象。
定義文本資料檔案的方法是:
file_name = [檔案名稱]
示例:
file_name = 'd:/python_data/data/text.txt'
檔案名稱中可以隻寫檔案名,此時預設Python讀取目前工作目錄下的檔案;也可以加入路徑,預設使用斜杠,尤其是Windows下要注意用法。
(2)擷取檔案對象
擷取檔案對象的意義是基于資料檔案産生對象,後續所有關于該資料檔案的操作都基于該對象産生。
文法:
file object = open(name , mode)
參數如下。
name:要讀取的檔案名稱,即上一個環節定義的file_name,必填。
mode:打開檔案的模式,選填。在實際應用中,r、r+、w、w+、a、a+是使用最多的模式。完整檔案打開模式如表2-1所示。
buffering:檔案所需的緩沖區大小,選填;0表示無緩沖,1表示線路緩沖。
傳回:
通過open函數會建立一個檔案對象(file object)。
file_name = 'text.txt'
file_object = open(file_name)
在“定義資料檔案”部分提到,可以将前兩個環節結合起來,定義的文法是:
file_object = open('text.txt')
(3)讀取檔案内容
Python基于檔案對象的讀取分為3種方法,如表2-2所示。
示例,在“附件-chapter2”檔案夾中有一個名為text.txt的資料檔案,其中包含2個文本行,資料内容如圖2-2所示。
通過read方法讀取該資料檔案得到的資料結果如下:
'line1: This is line1nline2: This is line2'
通過readline方法讀取該資料檔案得到的資料結果如下:
'line1: This is line1n'
通過readlines方法讀取該資料檔案得到的資料結果如下:
['line1: This is line1n', 'line2: This is line2
在實際應用中,read方法和readlines方法比較常用,而且二者都能讀取全部檔案中的資料。二者的差別隻是傳回的資料類型不同,前者傳回字元串,适用于所有行都是完整句子的文本檔案,例如大段文字資訊;後者傳回清單,适用于每行是一個單獨的資料記錄的檔案,例如日志資訊。不同的讀取方法會直接影響後續基于内容的處理應用。由于readline每次隻讀取一行資料,是以通常需要配合seek、next等指針操作,才能完整周遊讀取所有資料記錄。
(4)關閉檔案對象
每次使用完資料對象之後,需要關閉資料對象。方法是file_object.close()。這種應用方法略顯備援,這裡介紹基于with的檔案打開方法,該方式可以自動做上下文管理,而無須單獨做close操作。
例如,上面的檔案讀取方式用with可以寫成:
with open('text.txt') as fn:
content = fn.read()
如果同時要對多個檔案對象操作,那麼可以連續寫open方法。例如,同時對file1.txt和file2.txt做讀入可以這樣寫:
with open('file1.txt') as fn1, open('file2.txt') as fn2:
content1 = fn1.read()
content2 = fn2.read()
理論上,Python可以讀取任意格式的檔案,但在這裡通常以讀取格式化的文本資料檔案為主,其中包括有擴充名的txt、csv、tsv等格式的檔案,以及由固定分隔符分隔并以通用資料編碼和字元集編碼(例如utf8、ASCII、GB2312等)存放的無擴充名格式的資料檔案。在2.3節中我們會介紹使用Python讀取非結構化的資料的方法。
2.使用Numpy的loadtxt、load、fromfile讀取資料
Numpy讀取資料的方法包括loadtxt、load和fromfile 3種,概要描述如表2-3所示。
(1)使用loadtxt方法讀取資料檔案
Numpy可以讀取txt格式的資料檔案,資料通常都是一維或二維的。
loadtxt(fname, dtype=, comments='#', delimiter=None, converters=None, skiprows=0, usecols=None, unpack=False, ndmin=0)
- fname:檔案或字元串,必填,這裡指定要讀取的檔案名稱或字元串,支援壓縮的資料檔案,包括gz和bz格式。
- dtype:資料類型,選填,預設為float(64位雙精度浮點數)。Numpy常用類型如表2-4所示。
- comments:字元串或字元串組成的清單,是表示注釋字元集開始的标志,選填,預設為#。
- delimiter:字元串,用來分隔多個列的分隔符,例如逗号、TAB符,選填,預設值為空格。
- converters:字典,用來将特定列的資料轉換為字典中對應的函數的浮點型資料,例如将空值轉換為0,選填,預設為空。
- skiprows:跳過特定行資料,用來跳過特定前N條記錄,例如跳過前1行(可能是标題或注釋),選填,預設為0。
- usecols:元組,用來指定要讀取資料的列,第1列為0,以此類推,例如(1,3,5),選填,預設為空。
- unpack:布爾型,用來指定是否轉置數組,如果為真則轉置,選填,預設為False。
- ndmin:整數型,用來指定傳回的數組至少包含特定次元的數組,值域為0/1/2,選填,預設為0。
從檔案中讀取的數組。
在“附件-chapter2”檔案夾中有一個名為numpy_data.txt的資料檔案,資料為3行5列的矩陣,資料内容如圖2-3所示。該示例通過loadtxt方法讀取其中的資料。
import numpy as np # 導入Numpy庫
file_name = 'numpy_data.txt' # 定義資料檔案
data = np.loadtxt(file_name, dtype='float32', delimiter=' ') # 擷取資料
print(data) # 列印資料
上述代碼輸出的結果如下:
[[ 0. 1. 2. 3. 4.]
[ 5. 6. 7. 8. 9.]
[ 10. 11. 12. 13. 14.]]
(2)使用load方法讀取資料檔案
使用Numpy的 load方法可以讀取Numpy專用的二進制資料檔案,從npy、npz或pickled檔案加載數組或pickled對象,該檔案通常基于Numpy的save或savez等方法産生。
load(file, mmap_mode=None, allow_pickle=True, fix_imports=True, encoding='ASCII')
- file:類檔案對象或字元串格式,要讀取的檔案或字元串,必填。類檔案對象需要支援seek()和read()方法。
- mmap_mode:記憶體映射模式,值域為:None、'r+'、'r'、'w+'、'c',選填。
- allow_pickle:布爾型,決定是否允許加載存儲在npy檔案中的pickled對象數組,選填,預設值為True。
- fix_imports:布爾型,如果為True,pickle将嘗試将舊的Python 2名稱映射到Python 3中并使用的新名稱,僅在Python 2生成的pickled檔案加載Python 3時才有用,選填,預設值為True。
- encoding:字元串,決定讀取Python 2字元串時使用何種編碼,僅對Python 3讀取Python 2産生的pickled檔案時有用,選填。
從資料檔案中讀取的數組、元組、字典等。
我們将在這個示例中先定義一份資料,然後儲存為.npy格式的資料檔案(該檔案也在“附件-chapter2”中,名為load_data.npy),接着使用Numpy的load方法讀取并列印輸出。代碼如下:
import numpy as np # 導入Numpy庫
write_data = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])# 定義要存儲的資料
np.save('load_data', write_data) # 儲存為npy資料檔案
read_data = np.load('load_data.npy') #讀取npy檔案
print(read_data) # 輸出讀取的資料
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
(3)使用fromfile方法讀取資料檔案
使用Numpy的fromfile方法可以讀取簡單的文本檔案資料以及二進制資料。通常情況下,該方法讀取的資料來源于Numpy的tofile方法,即通過Numpy的tofile方法将特定資料儲存為檔案(預設為二進制資料檔案,無論檔案擴充名如何定義),然後通過fromfile方法讀取該二進制檔案。
fromfile(file, dtype=float, count=-1, sep='')
- file:檔案或字元串。
- dtype:資料類型,具體參照表2-3。注意資料類型要與檔案存儲的類型一緻。
- count:整數型,讀取資料的數量,-1意味着讀取所有資料。
- sep:字元串,如果file是一個文本檔案,那麼該值就是資料間的分隔符。如果為空("")則意味着file是一個二進制檔案,多個空格将按照一個空格處理。
從檔案中讀取的資料。
我們仍然以“附件-chapter2”檔案夾中numpy_data.txt資料檔案為例,首先通過tofile方法建立1個二進制檔案,然後對該檔案進行讀取。
import numpy as np # 導入Numpy庫
file_name = 'numpy_data.txt' # 定義資料檔案
data = np.loadtxt(file_name, dtype='float32', delimiter=' ') #擷取資料
tofile_name = 'binary' # 定義導出二進制檔案名
data.tofile(tofile_name) # 導出二進制檔案
fromfile_data = np.fromfile(tofile_name, dtype='float32') # 讀取二進制檔案
print(fromfile_data) # 列印資料
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.]
3.使用Pandas的read_csv、read_fwf、read_table讀取資料
相對于Python預設函數以及Numpy讀取檔案的方法,Pandas讀取資料的方法更加豐富。Pandas讀取文本檔案資料的常用方法如表2-5所示。
(1)使用read_cvs方法讀取資料
通過read_csv方法可以讀取csv格式的資料檔案。
read_csv(filepath_or_buffer, sep=',', delimiter=None, header='infer', names=None, index_col=None, usecols=None, **kwds)
參數(read_csv的參數衆多,僅介紹最常用的幾個如下。
- filepath_or_buffer:字元串,要讀取的檔案對象,必填。
- sep:字元串,分隔符号,選填,預設值為英文逗号','。特殊情況下,如果資料分隔符号含有多個,例如多列之間通過“|+|”(3個符号)分隔的,那麼分隔符sep的值可以設定為“|+|”,這是Python正規表達式文法。
- names:類數組,列名,選填,預設值為空。
- engine:解析引擎,預設情況下設定為“python”,這樣設定的好處是功能更全面;而如果設定為“c”則解析速度更快,在大檔案解析時更好用。但是,并不是所有情況下都可以設定為“c”,例如在上面的sep解析規則中,如果設定為“|+|”則無法指定解析引擎為“c”。
- skiprows:類字典或整數型,要跳過的行或行數,選填,預設為空。
- nrows:整數型,要讀取的前記錄總數,選填,預設為空,常用來在大型資料集下做初步探索之用。
- na_values:NA值的表現字元串,系統中已經預設支援将空格(‘’)、#N/A、#N/A N/A、 #NA、-1.#IND、-1.#QNAND、1.#QNAN、N/A、NA、NULL、NaN、nan識别為NA值,如果資料中有其他NA值的表現形式,可以在這裡指定。例如,設定na_values=[' ','None'],将字元串空格和None識别為NA值。
- thousands:字元串,千位符符号,選填,預設為空。
- decimal:字元串,小數點符号,選填,預設為點(.),在特定情況下應用。例如,歐洲的千位符和小數點與中國地區相反,歐洲的“4.321,1”對應中國的“4,321.1”。
- encoding:檔案編碼,預設情況下是“utf-8”,但需要注意的是,從原始資料庫中導出的資料可能有各種編碼,例如gb2312、latin1等,是以這裡要設定為與原始資料一緻的編碼格式。
DataFrame或TextParser
我們以“附件-chapter2”檔案夾中的csv_data.csv資料檔案為例,直接讀取檔案并列印輸出。資料内容如圖2-4所示。
import pandas as pd # 導入Pandas庫
csv_data = pd.read_csv('csv_data.csv', names=['col1', 'col2', 'col3', 'col4', 'col5']) # 讀取csv資料
print(csv_data) # 列印輸出資料
col1 col2 col3 col4 col5
0 0 1 2 3 4
1 5 6 7 8 9
2 10 11 12 13 14
(2)使用read_fwf方法讀取資料
通過read_fwf方法可以讀取表格或固定寬度格式的文本行到資料框。
read_fwf(filepath_or_buffer, colspecs='infer', widths=None, **kwds)
read_fwf與read_csv一樣都具有非常多的參數(隻是在文法中前者通過**kwds省略了,查詢完整文法請使用help(pd.read_fwf)),并且大多數參數的用法相同。除了read_csv中的常用參數外,以下介紹一個read_fwf特有且常用的參數。
- widths:由整數組成的清單,選填,如果間隔是連續的,可以使用字段寬度清單而不是“colspecs”。
DataFrame或TextParser。
我們以“附件-chapter2”檔案夾中的fwf_data資料檔案為例,直接讀取檔案并列印輸出。資料内容如圖2-5所示。
import pandas as pd # 導入Pandas庫
fwf_data = pd.read_fwf('fwf_data', widths=[5, 5, 5, 5], names=['col1', 'col2', 'col3', 'col4']) # 讀取csv資料
print(fwf_data) # 列印輸出資料
col1 col2 col3 col4
0 a2331 a9013 a3211 a9981
1 b4432 b3199 b9766 b2212
2 c3294 c1099 c7631 c4302
(3)使用read_table方法讀取資料
通過read_table方法可以讀取通用分隔符分隔的資料檔案到資料框。
read_table(filepath_or_buffer, sep='t', delimiter=None, header='infer', names=None, index_col=None, usecols=None, **kwds)
對于read_table而言,參數與read_csv完全相同。其實read_csv本來就是read_table中分隔符是逗号的一個特例,表現在文法中是read_csv的sep=','(預設)。是以,具體參數請查閱read_csv的參數部分。
我們以“附件-chapter2”檔案夾中的table_data.txt資料檔案為例,直接讀取檔案并列印輸出。資料内容如圖2-6所示。
import pandas as pd # 導入Pandas庫
table_data = pd.read_table('table_data.txt', sep=';', names=['col1', 'col2', 'col3', 'col4', 'col5']) # 讀取csv資料
print(table_data) # 列印輸出資料
col1 col2 col3 col4 col5
資料分隔(或分列)常用思路分為兩種:一種是基于固定寬度,一種是基于分隔符号。在表2-5所示的3種方法中,常用的是第2種和第3種,即read_fwf和read_table方法。
除了上述用于讀取文本檔案的方法外,Pandas還提供了非常豐富的用于其他場景的資料讀取方法,限于篇幅,在此不做更多介紹,僅提供讀取方法清單供有興趣的讀者參考,以及做知識延伸。具體如表2-6所示。
4.如何選擇最佳讀取資料的方法
關于“最佳”方法其實沒有固定定義,是以所謂的最佳方法往往與以下具體因素有關。
- 資料源情況:資料源中不同的字段類型首先會制約讀取方法的選擇,文本、數值、二進制資料都有各自的适應方法限制。
- 資料處理目标:讀取資料往往是第1步,後續會涉及資料探索、預處理、統計分析等複雜過程,這些複雜過程需要用到哪些方法在一定程度上都會受資料源的讀取影響,影響最多的包括格式轉換、類型轉換、異常值處理、分類彙總等。
- 模型資料要求:不同的模型對于資料格式的要求是不同的,應用到實際中不同的工具對于資料的表示方法也有所差異。
- “手感”最好的方法:很多時候,最佳方法往往是對哪個或哪些方法最熟悉,這些所謂的“手感”最好的方法便是最佳方法。
當然,即使使用了不是“最佳”的資料讀取方法也不必過于擔心,因為Python強大的功能提供了衆多可以互相進行轉換的方法。從Python存儲資料的基本對象類型來看,無非是字元串、清單、字典、元組、數組、矩陣等(當然,不同的庫對于這些對象的定義名稱可能有所不同,但基本含義相同),不同對象的類型轉換都非常容易。但本着少走彎路的原則,在這裡筆者還是針對不同的場景提供了較為适合的資料讀取方法。
- 對于純文字格式或非格式化、非結構化的資料,通常用于自然語言處理、非結構化文本解析、應用正規表達式等後續應用場景下,Python預設的3種方法更為适合。
- 對于結構化的、純數值型的資料,并且主要用于矩陣計算、資料模組化的,使用Numpy的loadtxt方法更為友善,例如本書中使用的sklearn本身就依賴于Numpy。
- 對于二進制的資料處理,使用Numpy的load和fromfile方法更為合适。
- 對于結構化的、探索性的資料統計和分析場景,使用Pandas方法進行讀取效果更佳,因為其提供了類似于R的資料框,可以實作“仿SQL”式的操作方式,對資料進行任意翻轉、切片(塊等)、關聯等都非常友善。
- 對于結構化的、數值型和文本型組合的資料統計分析場景,使用Pandas更為合适,因為每個資料框中幾乎可以裝載并處理任意格式的資料。
2.2.2 從Excel擷取營運資料
現有的Excel分為兩種格式:xls(Excel 97-2003)和xlsx(Excel 2007及以上)。
Python處理Excel檔案主要是第三方子產品庫xlrd、xlwt、pyexcel-xls、xluntils和pyExcel-erator等,此外Pandas中也帶有可以讀取Excel檔案的子產品(read_excel)。
基于擴充知識的目的,我們使用xlrd子產品讀取Excel資料。
首先安裝該庫,本書推薦的Anaconda中已經預設安裝了xlrd和xlwt子產品,用于Excel的讀寫操作。如果讀者系統環境中沒有,可以在Jupyter輸入指令!pip install xlrd安裝。
然後我們以“附件-chapter2”檔案夾中的demo.xlsx資料檔案為例,介紹該庫的具體應用。資料概覽如圖2-7所示。
import xlrd # 導入庫
# 打開檔案
xlsx = xlrd.open_workbook('demo.xlsx')
# 檢視所有sheet清單
print('All sheets: %s' % xlsx.sheet_names())
上述代碼中,我們先讀取一個Excel檔案,輸出檔案的sheet名稱清單。由于裡面隻有一張sheet,一次隻有一個值。結果為:All sheets: ['Sheet1']。
檢視sheet1的資料概況:
sheet1 = xlsx.sheets()[0] # 獲得第1張sheet,索引從0開始
sheet1_name = sheet1.name # 獲得名稱
sheet1_cols = sheet1.ncols # 獲得列數
sheet1_nrows = sheet1.nrows # 獲得行數
print('Sheet1 Name: %snSheet1 cols: %snSheet1 rows: %s' % (sheet1_name, sheet1_cols, sheet1_nrows))
我們分别擷取了第1張sheet(雖然裡面隻有一張,但在多sheet情況下可通過索引循環輸出)的名稱、列數量和行資料。結果如下:
Sheet1 Name: sheet1
Sheet1 cols: 4
Sheet1 rows: 10
檢視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: %snCol 2: %snCell 1: %sn' % (sheet1_nrows4, sheet1_cols2, cell23))
通過檢視特定行、列或行列組合的索引來輸出,結果如下:
Row 4: ['431381197408191515', '有效', 42725.0, '深圳市']
Col 2: ['Create_Time', 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0, 42725.0]
Cell 1: 深圳市
檢視sheet1的資料明細:
for i in range(sheet1_nrows): # 逐行列印sheet1資料
print(sheet1.row_values(i))
逐條輸出結果,部分結果如下(為了節約篇幅,中間的資料内容以…代替):
['ID_number', 'Status', 'Create_Time', 'Business_City']
['431381198109106573', '有效', 42725.0, '深圳市']
['431381198809122734', '有效', 42725.0, '深圳市']
…
['431381198901176911', '有效', 42725.0, '深圳市']
['43138119870827275X', '有效', 42725.0, '深圳市']
上述操作隻是将資料從Excel中讀取出來,将讀取的資料轉換為數組便可以進行矩陣計算。由于矩陣計算大多是基于數值型資料實作的,是以上述資料将無法适用于大多數科學計算場景,這點需要注意。
總結:在企業實際場景中,由于Excel本身的限制和适用,其無法存儲和計算過大(例如千萬級的資料記錄)的資料量,并且Excel本身也不是為了海量資料的應用而産生的,是以,Excel可以作為日常基本資料處理、補充資料來源或者彙總級别的資料進行讀取,同時也可以作為資料結果展示的載體,這種應用下對于大量數值表格的應用效果非常好。
2.2.3 從關系型資料庫MySQL讀取營運資料
在1.2.4節中我們介紹了安裝MySQL和Navicat的方法和關鍵步驟。這裡我們介紹如何利用Python從MySQL中讀取資料。
在“附件-chapter2”檔案夾中有一個名為order.xlsx的資料檔案,我們先把檔案導入MySQL資料庫,然後再基于資料庫進行相關操作。
第一步,建立一個資料庫用于存放要導入的目标資料。
1)打開Navicat,左側導航欄中有我們已經建立好的資料庫連結,在第1章中我們已經建立好了本地連接配接,名為“local”。
2)輕按兩下該資料庫連接配接,會展示出所有目前連接配接(對應的使用者權限)下可用的資料庫,如圖2-8所示。
3)為了保持不同資料的獨立性,我們建立一個資料庫,單獨存放特定主題的資料。在“local”名稱上右擊,在彈出的菜單中選擇,然後設定各項并單擊“确定”按鈕,如圖2-9所示。完成之後在左側的“local”連結下會新增一個剛才建立的資料庫“python_data”。
第二步,将Excel資料導入資料庫。
輕按兩下剛才建立的名為“python_data”的資料庫名稱,激活資料庫連接配接。此時右側功能欄中的部分功能已經可用。單擊“導入向導”,開始導出Excel資料,如圖2-10所示。
1)選擇資料檔案格式為Excel 2007檔案。
2)選擇資料源檔案,如圖2-11所示。
3)定義附加選項。由于資料檔案中第1行是表頭,是以資料從第2行開始。日期分隔符與資料檔案一緻,需要設定為“-”,其他都為預設值,如圖2-12所示。
4)設定目标資料表名。源表為“Sheet1”,目标表為“order”。
5)設定字段類型、長度、限制等資訊。其中主要的設定是将order_data類型設定為date(日期型),長度為0(不做限制);order_tme類型設定為time(時間型),長度為0(不做限制);total_amount類型設定為float(浮點型),長度預設為255,如圖2-13所示。
6)設定導入模式。由于我們是新建立表,是以設定為:“添加記錄到目标表”。
7)啟動導入任務。單擊“開始”按鈕即可。
等待系統導入資料。導入成功後,會在視窗中顯示一些資訊,最終的資訊中包含“success-fully”,如圖2-14所示。單擊“關閉”按鈕即可。
至此我們已經成功導入資料,在資料庫python_data下新增了一個名為“order”的資料表。我們要初步驗證導入的資料是否與原始資料一緻。
輕按兩下打開該表。打開表之後,會彈出資訊,提示該表沒有主鍵。但這并不影響我們使用該表,單擊“确定”按鈕即可,如圖2-15所示。
在建立表時,我們完全可以指定主鍵,例如本案例中的order_id是唯一的,那麼可指定該字段作為主鍵,更可以建立一個自增長ID作為主鍵。本節的主要内容是介紹如何導入外部資料到資料庫,有關資料庫建表還有很多話題,在此不做更多介紹。
打開order表之後,會顯示表預覽内容,如圖2-16所示。
一般情況下,MySQL以及資料都是存儲在C槽的。當不斷寫入大資料量時可能導緻C槽的空間急劇減少。由于很多應用程式(也包括MySQL)會在C槽占用很多臨時空間,是以當C槽突然變小時,可能導緻程式無法正常運作。此時可以檢查是否是MySQL不斷寫庫而導緻的。
在目前視窗,單擊“檔案-查詢表”或直接使用快捷鍵Ctrl+Q,打開SQL視窗,然後輸入SELECT * FROM
order
LIMIT 5;點選“運作”或使用快捷鍵Ctrl+R,傳回前5條結果,如圖2-17所示。讀者可以在此輸入其他SQL,或直接浏覽資料表來核對資料導入是否準确。
導入Excel資料主要核對的資訊點如下。
- 資料記錄數是否一緻:使用SELECT COUNT(*) FROM
;或在導入成功提示視窗也可以看到)。order
- 資料字段數量是否一緻,導入表中的字段不能多也不能少。
- 檢視資料内容是否一緻,尤其是日期、時間等非字元串字段的資料,很多時候時間型的資料轉換會出現0000-00-00,這通常是導入設定的日期分隔符問題。
- 資料精準度是否一緻,尤其是當原始資料是浮點型,要注意對應到資料庫字段是否還是浮點型(注意小數位數),問題通常出現在字段類型和位數設定上。
- 注意字段的最大長度,不同的數值型資料長度位數是不同,例如整數型tinyint、int,浮點型的單精度和雙精度浮點等,這對于彙總級别的資料會産生極大影響(因為某些字段的彙總資料可能非常大)。
通過Python連接配接MySQL需要有Python庫來建立連接配接,本節使用MySQL官方驅動連接配接程式,更多資訊可在1.2.3節中找到。
以下是Python讀取資料庫資料的基本方法:
上述代碼中,實作了通過Python連接配接MySQL查詢所有的資料,并輸出前2條資料的功能。執行結果如下:
('3897894579', datetime.date(2010, 3, 11), datetime.timedelta(0), 'PENDING_ORDER_CONFIRM', '1038166', 59.0)
('3897983041', datetime.date(2010, 3, 11), datetime.timedelta(0), 'REMOVED', '1041656', 19.9)
在應用MySQL中,除了查詢所有資料外,更多時候我們還會應用更多SQL技巧來幫助我們快速找到目标資料并做初步處理。以下是常用SQL文法。
1)隻查詢前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;。
2)隻查詢特定列(而非全部列)資料。
示例:隻查詢total_amount和order_id兩列資料。
SELECT total_amount, order_id from
order
;
選擇特定列隻需将列名寫到表達式中即可,多個列名用英文逗号分隔。另外,還可以使用“表名.字段名”的寫法,例如上述表達式可以寫成SELECT order.total_amount, order.order_id from
order
;,這種寫法會出現在表達式中有多個表的情況下,例如多表關聯查詢。
3)查詢特定列去重後的資料。
示例:查詢針對user_id去重後的資料。
SELECT DISTINCT user_id FROM
order
關鍵詞DISTINCT用于傳回唯一不同的值,後面接字段名即要去重的字段。如果後面接多個字段會預設對多個字段同時進行比較,隻有多個字段完全相同時才會去重。DISTINCT常用來傳回去重後的特定ID,或者與COUNT配合使用,查詢特定資料記錄的唯一數量。
4)查詢帶有1個條件的資料。
示例:查詢total_amount<100的所有資料。
order
WHERE total_amount < 100;
WHERE是條件關鍵字,後面接具體條件。本示例中,由于total_amount為浮點型,是以可直接與數值型比較;如果是字元串型,則比較值需要加引号用來表示一緻的字段類型。
5)查詢帶有多個條件(同時滿足)的資料。
示例:查詢total_amount<100且status為REMOVED的所有資料。
order
WHERE total_amount < 100 and
status
= 'REMOVED';
多個條件使用and表示且的關系,多個條件必須同時滿足。MySQL中字段不區分大小寫。由于status也是關鍵字,是以也需要使用
status
。
6)查詢帶有多個條件(滿足任意一個)的資料。
示例:查詢total_amount<100或status為REMOVED的所有資料。
order
WHERE total_amount < 100 or
status
多個條件使用or表示或的關系,多個條件滿足任意一個條件即可。
7)查詢特定條件值在某個值域範圍内的資料。
示例:查詢status的值為REMOVED或NO_PENDING_ACTION或PENDING_ORDER_CONFIRM。
order
WHERE
status
in ('REMOVED','NO_PENDING_ACTION','PENDING_ORDER_CONFIRM');
對于特定字段采用窮舉法列出值域的方法,也可以使用or方法連接配接多個條件,但使用清單的窮舉法會使得表達式更簡單。
8)使用正規表達式查詢具有複雜條件的資料。
示例:查詢user_id以“103”開頭且order_id包含“04”的所有訂單資料。
order
WHERE user_id LIKE '103%' and order_id LIKE '%04%';
正規表達式通常用在複雜條件中,通過使用關鍵字LIKE來連接配接不同的正則文法,LIKE後面接具體的比對模式。常用的比對模式如下。
以特定字元開頭:'字元串%',例如'ABD%'表示以ABD開頭的所有比對。
以特定字元結尾:'%字元串',例如'% ABD'表示以ABD結尾的所有比對。
包含特定字元:'%字元串%',例如'%ABD%'表示包含ABD的所有比對。
正規表達式還有更多強大的文法規則,限于篇幅不再展開介紹。
9)将查詢到的資料倒序排列。
示例:将total_amount金額在10~100之間的所有資料,按照訂單ID倒序排序。
order
WHERE 10 < total_amount < 100 ORDER BY order_id DESC;
在查詢表達式ORDER BY的結尾,通過使用DESC來表示倒序(逆序)排序;省略是預設使用ASC正序(順序)排序。
10)查詢指定列中不包含空值的所有資料。
示例:查詢order_id不為空的所有資料。
order
WHERE order_id IS NOT NULL;
在MySQL中,IS NULL表示為空,IS NOT NULL表示非空。需要注意的是,NULL不代表空字元串或者空格,而是真正意義上的沒有任何資料,類似于Python中的None。
上述案例隻是展示了如何取數,更多情況下,我們會配合特定函數和方法做資料計算、整合和探索性分析。例如:
- 使用MySQL聚合函數求算術平均值、計數、求最大/最小值、做分類彙總等。
- 使用MySQL數學函數,用來求絕對值,進行對數計算、求平方根等。
- 使用MySQL字元串函數進行字元串分割、組合、截取、比對、處理等。
- 使用MySQL的日期函數進行日期擷取、轉換、處理等。
- 使用MySQL将多個表(2個或2個以上)資料進行關聯、比對和整合。
在Python工作者看來,Python本身能勝任MySQL的很多工作,為什麼還要耗費時間和精力學習如何在MySQL中完成這些資料工作呢?直接用Python讀取資料然後基于Python的相關庫進行資料運算豈不更好?
Python的工作強項并不是資料計算,而是其靈活、高效、簡易和內建多方的工作方式、效率和效果。MySQL(以及其他關系型資料庫)作為成熟的資料存儲和內建解決方案,在(關系型)資料本身方面更具優勢,尤其是對于資料結構定義(實體、屬性、關系)、關系操作(選擇、連接配接、聚合等)、關系完整性限制(主外鍵、唯一性等)等方面具有成熟且穩定的應用價值,這對于資料處理至關重要。是以,可以說MySQL在結構化資料存儲和初步處理工作上比Python更專業。
還有一個更加關鍵的原因是,如果所有資料工作都由Python完成,那麼Python的事務處理在某些情況下一定會面臨資源瓶頸、工作效率等問題,屆時可能會導緻程式崩潰和報錯,這将大大降低程式的可靠性以及結果輸出的效率,對于海量資料工作更是如此。
是以,很多時候不是Python不能做,而是在合适的時機選擇最合适的工具來完成才是最好的選擇。
2.2.4 從非關系型資料庫MongoDB讀取營運資料
由于MongoDB一般都是企業級資料存儲,是以這裡我們使用在第1章已經安裝過的SSH遠端用戶端SecureCRT。如果讀者有自己在虛拟機或本地安裝MongoDB,也可以使用,操作方法類似。
輕按兩下SecureCRT打開程式,單擊頂部的快速連接配接按鈕,建立連接配接,如圖2-18所示。
然後根據伺服器具體配置情況,配置如圖2-19所示資訊。其中主機名和使用者名需要單獨配置,其他則應根據實際情況詢問IT或運維管理人員(本案例中都是預設值)。可勾選
用于以後啟動該程式時直接顯示快捷入口。
單擊“連接配接”按鈕之後,會彈出密碼輸入視窗,輸入密碼,可勾選
用于以後無須重複輸入密碼,具體視公司安全規定執行,如圖2-20所示。
如果伺服器配置資訊填寫正确,連接配接伺服器成功會顯示如圖2-21所示資訊。
要想通過Python調用MongoDB,需要先安裝PyMongoDB,本書使用的Anaconda預設沒有安裝該庫,可在Jupyter中直接使用!pip install pymongo安裝。
使用Python連接配接MongoDB之前,需要伺服器上的MongoDB處于啟動狀态。檢視是否成功啟動的方法是找一個可以直接連接配接或通路伺服器的浏覽器,直接輸入IP:端口,如果出現“It looks like you are trying to access MongoDB over HTTP on the native driver port.”字樣的提示,則說明已經正常啟動和運作。例如:筆者的伺服器上已經啟動了該服務,在浏覽器中輸入
http://10.66.202.134:27017/後提示如圖2-23所示資訊。
要在伺服器上進入Python環境,直接在終端視窗輸入指令python。在Python指令行視窗中,通過如下方法調用MongoDB資料。
from pymongo import MongoClient # 導入庫
client = MongoClient('10.0.0.54', 27017) # 輸出實際的伺服器IP位址以及端口,建立連接配接,并初始化環境變量
db = client.python_data # 選擇python_data庫
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()) # 擷取一條文檔資料
在上述代碼中,我們連接配接到MongoDB後選擇了test_py庫下的ordersets集合,然後插入2條資料到集合中,列印其中一條資料如下:
{'_id': ObjectId('5bf51b668b0b3f20dcc04638'), 'user': 'tony', 'id': '31020', 'age': '30', 'products': ['215120', '245101', '128410'], 'date': '2017-04-06'}
再輸出所有集合資料。
for i in orders.find(): # 擷取所有文檔資料并展示
print(i)
以下是代碼執行後列印輸出的結果:
{'age': '30', 'products': ['215120', '245101', '128410'], 'user': 'tony', 'date': '2017-04-06', '_id': ObjectId('58eb1f0b2f76bf26108b4898'), 'id': '31020'}
{'age': '29', 'products': ['541001', '340740', '450111'], 'user': 'lucy', 'date': '2017-04-06', '_id': ObjectId('58eb1f0b2f76bf26108b4899'), 'id': '32210'}
除了上述基本查詢語句外,PyMongo也提供了類似于MySQL的條件過濾語句。
1)查詢特定文檔資料。
示例:隻查詢第2條資料。
orders.find()[1] # 查詢特定索引的資料記錄
通過增加索引值可以指定查詢特定索引的文檔資料。注意索引值從0開始,0代表第1條是資料。
2)查詢特定範圍内的文檔資料。
示例:隻查詢第1~2條資料。
orders.find()[0:2] # 查詢特定範圍内的資料記錄
通過增加索引值可以指定查詢特定索引範圍的文檔資料(切片)。注意,索引值為空則預設從0開始,0代表第1條是資料。上述表達式可以寫成orders.find()[:2]。索引結束值預設不包含,例如,上述文法中的0:2的實際索引隻有0和1。
3)增加查詢條件。
示例:隻查詢user為lucy的文檔資料。
orders.find({"user": "lucy"}) # 所有資料,注意使用疊代方法檢視資料
orders.find_one({"user": "lucy"}) # 單條資料
作為Key-Value形式的代表應用之一,MongoDB幾乎所有的用法都以Key-Vaule的形式存在。過濾條件也不例外,隻需在find函數中,以Key-Value的形式設定過濾條件即可,其中Key為過濾次元,Value為對應值。
4)排序。
示例:針對user排序并輸出。
orders.find({"user": "lucy"}).sort("user") # 所有資料,注意使用疊代方法檢視資料
通過使用Sort方法設定排序次元。預設是正序,也可以指定為倒序排列,同時也可以指定多個字段排序規則,例如collection.find().sort([ ('field1', pymongo.ASCENDING), ('field2', pymongo.DESCENDING)])。從MongoDB 2.6開始,還提
供了按照文本相關性的排序方法,例如collection.find({'score': {'$meta': 'text-Score'}}).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資訊。
1)獲得百度賬戶,沒有賬戶的讀者可在
https://passport.baidu.com/v2/?reg免費注冊擷取。
2)注冊成為百度開放平台開發者,讀者可進入
http://lbsyun.baidu.com/apiconsole/key?appl-ication=key完成相關注冊。該過程非常簡單,遵循引導即可,整個過程在5分鐘以内完成,如圖2-24所示。
3)注冊完成之後,會有一封名為“百度地圖開放平台”的開發者激活郵件發送驗證連結到使用者指定(注冊時郵箱)郵箱,單擊連結進行驗證。
4)單擊“申請秘鑰”進入建立應用界面,如圖2-25所示。在該應用建立中,我們主要使用Geocoding API v2,其他應用服務根據實際需求勾選,如圖2-26所示。如果不做限制,IP白名單區域設定為“0.0.0.0/0”。設定完成後,單擊“送出”按鈕。
5)獲得AK秘鑰。完成上述步驟之後,會預設跳轉到應用清單界面,界面中的“通路應用(AK)”中便是該應用的秘鑰,如圖2-27所示。
1.擷取并解析JSON資料
我們先通過Python請求該API來獲得JSON格式的資料。本示例的目标是給百度API發送一條地理位置資料,傳回其經緯度資訊。
本節會用到Python第三方庫requests,預設通過Anaconda已經安裝。如果讀者系統環境中沒有該庫,可以先通過!pip install requests安裝。完整代碼如下:
import requests # 導入庫
add = '北京市中關村軟體園' # 定義位址
ak = 'DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr' # 建立通路應用時獲得的AK
url = '
http://api.map.baidu.com/geocoder/v2/?address=%s&output=json&ak=%s' # 請求URL
res = requests.get(url % (add, ak)) # 獲得傳回請求
add_info = res.text # 傳回文本資訊
print(add_info) # 列印輸出
在上述代碼中,先導入一個requests庫,該庫用來發送網絡請求,支援多種發送模式,可以用來做網頁内容抓取、自動化網頁測試、網頁内容采集等。
第2行定義了一個位址,該位址通常是營運中的位址類資訊,例如:通信位址、注冊位址、收貨位址、聯系位址等。
第3行ak是建立通路應用時獲得的AK,注意百度有每天有6000次的限制,讀者可填寫自行申請的AK。
第4行定義了一個通過get方法發送的URL請求位址,位址中的address和ak的具體值使用占位符代替,在後面用到時具體指派,這種方法經常用于位址、ak有變化的場景中。例如:我們通常會建立多個應用(基于每個賬戶有限制,以及分開治理應用的考慮),然後從資料庫中讀取一系列位址用于解析。此時的位址和AK都需要能動态指派。
第5行通過get方法發送請求到上面定義的URL中,并具體指派。
第6行将傳回對象的文本資訊指派到add_info,傳回對象中還包括非常多的相關屬性資訊,例如狀态碼、cookie、reason、headers、編碼等,這些資訊可用于判斷是否正确傳回、問題原因、狀态等資訊。
最後一行列印輸出傳回的文本資訊。
{"status":0,"result":{"location":{"lng":116.29381532521775,"lat":40.05299113952319},"precise":0,"confidence":40,"comprehension":100,"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' # 獲得經緯度資訊
print(lat_lng) # 列印輸出
代碼中,我們導入Python自帶的JSON庫。該庫支援Python其他對象和JSON對象之間的互相轉換。
先将獲得的位址資訊格式化為JSON字元串(字典類型),然後通過讀取字典的Key來獲得其Value。由于傳回的位址資訊中包含字典嵌套,是以這裡需要依次讀出第1層和第2層資訊。讀者可通過add_json.items()來更加直覺地觀察2層嵌套。
上述代碼執行後傳回結果如下:
{'lng': 116.29381532521775, 'lat': 40.05299113952319}
2.擷取并解析XML資料
Geocoding API也提供XML格式的傳回資料。下面以獲得XML格式的資料為例介紹代碼過程。
http://api.map.baidu.com/geocoder/v2/?address=%s&output=xml&ak=%s上述所有代碼與JSON格式的代碼完全相同,隻在第4行定義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進行處理。
import xml.etree.ElementTree as Etree # 導入XML中的ElementTree方法
root = Etree.fromstring(add_info) # 獲得XML的根節點
lng = root1[0].text # 獲得lng資料
lat = root1[1].text # 獲得lat資料
print('lng: %s' % lng) # 格式化列印輸出經度值
print('lat: %s' % lat) # 格式化列印輸出緯度值
上述代碼中,前4行實作了一個功能,将代碼的字元編碼設定為utf-8,否則系統會預設為ASCII,對傳回的帶有中文字元串無法識别而報錯。
代碼第5行導入XML自帶的ElementTree方法,該方法可以實作對XML内容的查詢、建立、修改等操作,是XML中比較簡單容易上手的方法(XML除了ElementTree外,還提供了DOM和SAX方法)。
代碼第6行獲得從API得到的XML對象并獲得根節點。
代碼第7、第8行分别通過嵌套讀取從根節點開始向下的第3層經緯度資料。
代碼最後兩行格式化列印輸出經緯度。
lng: 116.293815325
lat: 40.0529911395
有關百度API的更多資訊,具體查閱
http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding在API應用中,中文的編碼處理因細節太多而常常讓人頭疼。是以,如果可以則應盡量減少直接在API的資料中出現中文字元。在實際企業應用中,會出現多種API形式,但無論哪種形式,其基本實作思路都是一緻的:導入庫→定義請求變量→發送請求→獲得傳回資料→格式化并獲得目标資料,是以需要掌握JSON和XML的資料與其他資料的轉換方法。
2.3 内容延伸:讀取非結構化網頁、文本、圖像、視訊、語音
在前面的章節中,我們介紹的内容是企業常見的資料來源和擷取方式。本節将拓展資料來源方式和格式的擷取,主要集中在非結構化的網頁、文本、圖像、視訊和語音。
2.3.1 從網頁中擷取營運資料
要從網頁中擷取資料,可使用Python内置标準庫或第三方庫,例如urllib、urllib2、httplib、httplib2、requests等。本節使用requests方法擷取網頁資料。
import requests # 導入庫
http://www.dataivy.cn/blog/dbscan/' # 定義要擷取的網頁位址
res = requests.get(url) # 獲得傳回請求
html = res.text # 傳回文本資訊
print(html) # 列印輸出網頁源代碼
在代碼中,先導入用到的網絡請求處理庫requests,然後定義一個用來擷取的url,通過requests的get方法擷取url的傳回請求,并通過傳回請求的text方法擷取内容(源代碼),最終列印輸出網頁資訊。部分結果如下:
從網頁中讀取的資訊其實是網頁的源代碼,源代碼經過浏覽器解析後才是我們看到的不同的頁面内容和效果。是以,在擷取網頁中包含了内容的源代碼後,下面要做的是針對源代碼的解析。有關該内容會在3.10.1節中具體說明。
2.3.2 讀取非結構化文本資料
非結構化的文本資料指的是文本資料中沒有結構化的格式,需要定制化解析才能擷取資料,并且每條記錄的字段也可能存在差異,這意味着傳統的結構化讀取方式将很難工作。非結構化的日志就是一個典型示例,伺服器的日志可由運維工程師自行定義,是以不同公司的日志格式會有所不同。另外在網站日志中還可能包含通過頁面“埋碼”的方式采集到的使用者的行為資料,這些都會使日志面臨非結構化的解析問題。
在“附件-chapter2”檔案夾中有一個名為traffic_log_for_dataivy的日志檔案,裡面存放了www.dataivy.cn 網站一段時間的日志資料。本節示例代碼的目的是将日志讀取出來。
file = 'traffic_log_for_dataivy'
fn = open(file, 'r') # 打開要讀取的日志檔案對象
content = fn.readlines() # 以清單形式讀取日志資料
print(content[:2])
fn.close() # 關閉檔案對象
上述代碼中先定義了一個要讀取的非結構化文本檔案,通過Python标準庫open方法以隻讀模式打開檔案,然後通過readlines方法将檔案内容以行為機關讀取為資料清單,列印輸出前2條資料,最後關閉檔案對象。執行後傳回如下結果:
['120.26.227.125 - - [28/Feb/2017:20:06:51 +0800] "GET / HTTP/1.1" 200 10902 "-" "curl"n', '139.129.132.110 - - [28/Feb/2017:20:06:51 +0800] "GET / HTTP/1.1" 200 10903 "-" "curl"n']
其實日志檔案隻是普通文本檔案的一種類型而已,其他的非結構化資料檔案都可以以類似的方法讀取,即使檔案沒有任何擴充名也可以。
總結:對于非結構化的文本處理,通常更多側重于特定場景,通用性較差,原因就在于非結構化的形式本身變化多樣。自然語言了解、文本處理和挖掘、使用者日志和機器日志解析等都是圍繞該領域的主要工作主題。
2.3.3 讀取圖像資料
在Python 3中,讀取圖像通常使用Pillow和OpenCV兩個庫,相對而言,筆者使用後者的情況更多。本節以“附件-chapter2”檔案夾中cat.jpg為例進行說明。
1.使用Pillow讀取圖像
有關Pillow與PIL的淵源,我們已經在1.2.3節中介紹過,這裡直接介紹Pillow的用法。
Pillow中包含很多庫,常用的是Image,通過使用其中的open方法來讀取圖像。用法如下:
from PIL import Image # 導入庫
file = 'cat.jpg' # 定義圖檔位址
img = Image.open(file, mode="r") # 讀取檔案内容
img.show() # 展示圖像内容
其中關鍵的方法是open,其參數包括以下兩個。
- file:檔案對象名稱,可以是檔案名,也可以是圖像檔案字元串。
- mode:打開模式,預設隻能是r模式,否則會報錯。當file是圖像字元串時,會調用系統的rb模式讀取。
通過open讀取之後會傳回一個圖像檔案對象,後續所有的圖像處理都基于該對象進行。上述代碼執行後,通過img.show()會調用系統預設的圖像浏覽器打開圖像進行檢視,如圖2-28所示。
該對象包含了很多方法,這些方法可以用來列印輸出檔案的屬性,例如尺寸、格式、色彩模式等。
print('img format: ', img.format) # 列印圖像格式
print('img size: ', img.size) # 列印圖像尺寸
print('img mode: ', img.mode) # 列印圖像色彩模式
上述代碼執行後傳回的結果如下:
img format: JPEG
img size: (435, 361)
img mode: RGB
其中圖像的類型是圖像本身的格式,例如jpg、gif、png等;圖像尺寸是指圖像分辨率,示例中的尺寸是435×361(機關是像素);圖像的模式指的是顔色模式,示例圖像是RGB模式。
除此以外,基于該檔案對象也可以進行其他操作,例如圖像格式轉換、旋轉、裁剪、合并、濾波處理、色彩處理、縮略圖處理等。限于篇幅,在此不做過多介紹。
2.使用OpenCV讀取圖像
在第1章介紹了OpenCV的安裝方法,但截至本書撰寫時,通過pip安裝的包僅為3.4.3版本。而此時4.0版本已經釋出,但通過其他方法無法安裝該版本。
OpenCV讀取和展示圖像主要使用cv2庫。
import cv2 # 導入庫
img = cv2.imread(file) # 讀取圖像
cv2.imshow('image', img) # 展示圖像
cv2.waitKey(0) # 與顯示參數配合使用
上述兩種方法執行後,都會産生如圖2-28所示的結果。不同的是,圖2-28中通過PIL調用的是系統預設的圖像顯示工具,而在OpenCV中是通過自身建立的圖像功能顯示圖像。
另外,兩種方法中都有一個waitKey()的方法,該方法的作用是鍵盤綁定函數,其中的參數表示等待毫秒數。執行該方法後,程式将等待指定的毫秒數,看鍵盤是否有輸入,然後傳回值對應的ASCII值。如果其參數為0,則表示無限期地等待,直到鍵盤有輸入。
筆者通常使用第2種方法讀取圖像,此方法更加簡單。其中imread方法細節如下。
cv2.imread(filename[, flags])
描述:
讀取圖像内容,如果圖像無法讀取則傳回空資訊。支援的圖像格式幾乎包括了日常所有場景下的格式。具體包括以下這些。
- Windows bitmaps檔案:*.bmp、*.dib。
- JPEG檔案:*.jpeg、*.jpg、*.jpe。
- JPEG 2000檔案:*.jp2。
- PNG檔案:*.png。
- WebP檔案:*.webp。
- 移動圖像格式:*.pbm、*.pgm、*.ppm *.pxm、*.pnm。
- Sun rasters檔案:*.sr、*.ras。
- TIFF 檔案:*.tiff、*.tif。
- OpenEXR檔案:*.exr。
- Radiance HDR檔案:*.hdr、*.pic。
參數:
filename必填,字元串,圖像位址。
flags可選,int型或對應字元串,顔色的讀取模式。如果flag>0或者cv2.IMREAD_COLOR,讀取具有R/G/B三通道的彩色圖像;如果flag=0或cv2.IMREAD_GRAYSCALE,讀取灰階圖像;如果flag<0或cv2.IMREAD_UNCHANGED,讀取包含Alpha通道的原始圖像。
圖像内容,如果圖像無法讀取則傳回NULL。
3.使用Matplotlib展示圖像
除了使用OpenCV自帶的圖像展示方法外,OpenCV還常與matplotlib配合展示圖像,這種場景更加常用。組合使用時可借用Matplotlib的強大圖像展示能力進行圖像的對比和參照以及不同圖像模式的輸出。
但是需要注意的是,使用OpenCV讀取彩色圖像時,OpenCV是以B、G、R的順序存儲和顯示圖像資料的,而Matplotlib是以R、G、B的順序顯示圖像的;如果直接使用OpenCV讀取圖像後調用Matplotlib顯示,那麼會與原始圖像不一緻。
下面通過執行個體代碼來示範如何通過Matplotlib顯示OpenCV讀取的圖像,以及OpenCV和Matplotlib顯示圖像的差異。
# 導入庫
import matplotlib.pyplot as plt
import cv2 # 導入庫
# 讀取圖像檔案并建立多圖像副本
file = 'cat.jpg' # 定義圖檔位址
img = cv2.imread(file) # 讀取圖像
b, g, r = cv2.split(img) # 分離顔色三通道
img2 = cv2.merge([r, g, b]) # 重新組合圖像資料
# 使用Matplotlib展示圖像
plt.subplot(121) # 定位第1個網格
plt.title('plt BGR image') # 設定子網格标題
plt.imshow(img) # 設定子網格展示的圖像
plt.subplot(122) # 定位第2個網格
plt.title('plt RGB image') # 設定子網格标題
plt.imshow(img2) # 設定子網格展示的圖像
# 使用OpenCV展示圖像
cv2.imshow('OpenCV BGR image', img) # 展示BGR圖像
cv2.imshow('OpenCV RGB image', img2) # 展示RGB圖像
cv2.waitKey(0) # 與顯示參數配合使用
cv2.destroyAllWindows() # 關閉所有視窗
上述代碼中,我們分别導入用到的matplotlib.pyplot和cv2庫,然後讀取圖像檔案并建立多圖像副本。其中涉及兩個新的參數用法:split和merge。
- split:使用cv2.split可以将OpenCV讀取的圖像資料,分離為B、G、R單顔色通道圖像。
- merge:使用cv2.merge将多個通道顔色資料以R、G、B的次序再次組合起來(跟img中的模式不同),形成img2。
使用Matplotlib展示圖像中,我們用到了以下參數:
- subplot:用來定位子網格的位置,預設參數包括subplot(nrows, ncols, plot_number),nrws為行數,ncols為列數,plot_number為網格位置,該位置以行為索引标準,行索引完畢之後再換另一行。例如,一個[4, 2, 3]的位置代表的是建立一個4行2列的網格,并定位在第3個子網格(第2行的第1個位置)。如果3個值都小于10,那麼可以組合并簡寫為一個3位數,例如本示例中寫為plt.subplot(121)或plt.subplot(1, 2, 1)都是可以的,二者是等效的。
- title:用來設定網格的标題。
- imshow:用來展示一個圖像對象。
使用Matplotlib展示的圖像結果如圖2-30所示。
使用OpenCV展示圖像中的參數基本都是我們之前用過的。其中的cv2.destroyAllWin-dows()用來關閉所有視窗,該函數在下面讀取視訊資料時還會用到。本段函數的展示圖像結果如圖2-31所示。
觀察通過Matplotlib和OpenCV讀取的圖像結果,會發現二者在預設模式下的顯示結果是不同的。是以,讀者如果要用Matplotlib展示OpenCV讀取的圖像結果,必須注意圖像顯示模式的差異和調整。
2.3.4 讀取視訊資料
Python讀取視訊最常用的庫也是Opencv。本節以“附件-chapter2”檔案夾中Megamind.avi的視訊為例進行說明,以下是一段讀取視訊内容的代碼示例。
import cv2 # 導入庫
cap = cv2.VideoCapture("tree.avi") # 獲得視訊對象
status = cap.isOpened() # 判斷檔案是否正确打開
# 輸出基本屬性
if status: # 如果正确打開,則獲得視訊的屬性資訊
frame_width = cap.get(3) # 獲得幀寬度
frame_height = cap.get(4) # 獲得幀高度
frame_count = cap.get(7) # 獲得總幀數
frame_fps = cap.get(5) # 獲得幀速率
print('frame width: ', frame_width) # 列印輸出
print('frame height: ', frame_height) # 列印輸出
print('frame count: ', frame_count) # 列印輸出
print('frame fps: ', frame_fps) # 列印輸出
# 讀取視訊内容并展示視訊
success, frame = cap.read() # 讀取視訊第1幀
while success: # 如果讀取狀态為True
cv2.imshow('vidoe frame', frame) # 展示幀圖像
success, frame = cap.read() # 擷取下1幀
k = cv2.waitKey(int(1000 / frame_fps)) # 每次幀播放延遲一定時間,同時等待輸入指令
if k == 27: # 如果等待期間檢測到按Esc鍵
break # 退出循環
# 操作結束釋放所有對象
cv2.destroyAllWindows() # 關閉所有視窗
cap.release() # 釋放視訊檔案對象
上述代碼分為4個部分,以空行分隔。
第一部分為前3行,先導入庫,然後讀取視訊檔案并獲得視訊對象,最後獲得視訊讀取狀态。其中的關鍵方法是VideoCapture,用來讀取圖像。
cv2.VideoCapture(VideoCapture ID|filename|apiPreference)
讀取視訊裝置或檔案,并建立一個視訊對象執行個體。
- VideoCapture ID:必填。int型,系統配置設定的裝置對象的ID,預設的裝置對象的ID為0。
- Filename:必填。包括如下部分。
- 視訊檔案的名稱,字元串,例如abc.avi。目前版本下隻支援avi格式。
- 序列圖像,字元串,例如img_%2d.jpg(圖像序列包括img_00.jpg, img_01.jpg, img_ 02.jpg, ...)。
- 視訊URL位址,字元串,例如protocol://host:port/script_name?script_params|auth。
- apiPreference:int型,背景使用的API。
一個視訊對象執行個體。
第2部分為if循環體内的9行代碼,該代碼主要用來在判斷檔案被正确讀取的情況下,輸出視訊檔案的整體資訊。除了代碼中get方法使用的參數值外,OpenCV還支援更多圖像屬性,如表2-7所示。
該段代碼輸出如下視訊資訊:
frame width: 320.0
frame height: 240.0
frame count: 444.0
frame fps: 14.999925000374999
第3部分為具體讀取和展示視訊的每一幀内容。首先讀取視訊的第1幀,如果狀态為True,則展示圖像并讀取下一幀,期間通過cv2.waitKey參數做圖像延遲控制,同時延遲期間等待系統輸入指定,如果有輸入Esc則退出循環讀取幀内容。視訊内容的截圖如圖2-32所示。
在視訊中有幾個關鍵名詞。
- 幀率(FPS):每秒播放的幀數被定義為幀率,幀率越高,在視覺上認為圖像越連貫,就越沒有卡頓的現象。常見的幀率包括23.967(電影)、25(PAL電視),示例圖像大約為15。幀率與圖像清晰度無關,它隻是決定了視訊的連貫性。
- 幀分辨率:幀分辨率基本決定了視訊的清晰度(除此之外還有視訊處理效果、裝置播放差異等,這裡指的是同等條件下的視訊源)。在同樣大小的圖像中,分辨率越高圖像通常就會越清晰。是以形容視訊時提到的1080P(1920×1080)、720P(1280×720)其實指的就是分辨率标準。當然,對于同樣分辨率下,在不同國家、不同電視規制、不同掃描标注下,也會更加細分。
第4部分為當所有操作結束後,删除所有由OpenCv建立的窗體,釋放視訊檔案對象。
有關OpenCV的更多資訊,具體可查閱opencv.org。
2.3.5 讀取語音資料
對于語音檔案的讀取,可以使用Python的audioop、aifc、wav等庫實作。但針對語音處理這一細分領域,目前市場上已經具備非常成熟的解決方案,例如科大訊飛、百度語音等。大多數情況下,我們會通過調用其API實作語音分析處理的功能,或者作為分析處理前的預處理功能。
在具體實作過程中,既可以直接下載下傳SDK做離線應用,也可以使用線上的服務。科大訊飛的語音服務如圖2-33所示。
本節将以百度語音API服務應用為例,說明如何通過請求百度語音的API,将語音資料轉換為文字資訊。
在正式應用百度語音API之前,請讀者先參照2.2.5節中介紹的步驟,建立百度賬戶并注冊成為百度開發者。基于該條件下,我們繼續開通語音識别服務。具體方法如下:
1)進入
http://yuyin.baidu.com/app,在彈出的界面中單擊要針對哪個應用開通語音識别服務。我們預設使用在之前建立的API_For_Python應用。是以,單擊該應用的“開通服務”,如圖2-34所示。
2)在彈出的視窗中,單擊選擇“語音識别”并确定,如圖2-35所示。
3)開通成功後系統會提示,然後單擊圖2-36中右側的,會彈出如圖2-36所示資訊。
彈出的API Key和Secret Key為在後續語音識别中要使用的資訊。
以下為完整代碼:
import json # 用來轉換JSON字元串
import base64 # 用來做語音檔案的Base64編碼
import requests # 用來發送伺服器請求
# 獲得token
API_Key = 'DdOyOKo0VZBgdDFQnyhINKYDGkzBkuQr' # 從申請應用的key資訊中獲得
Secret_Key = 'oiIboc5uLLUmUMPws3m0LUwb00HQidPx' # 從申請應用的key資訊中獲得
token_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=%s&client_secret=%s" # 獲得token的位址
res = requests.get(token_url % (API_Key, Secret_Key)) # 發送請求
res_text = res.text # 獲得請求中的文字資訊
token = json.loads(res_text)['access_token'] # 提取token資訊
# 定義要發送的語音
voice_file = 'baidu_voice_test.pcm' # 要識别的語音檔案
voice_fn = open(voice_file, 'rb') # 以二進制的方式打開檔案
org_voice_data = voice_fn.read() # 讀取檔案内容
org_voice_len = len(org_voice_data) # 獲得檔案長度
base64_voice_data = base64.b64encode(org_voice_data).decode('utf-8')
# 将語音内容轉換為base64編碼格式
# 發送資訊
# 定義要發送的資料主體資訊
headers = {'content-type': 'application/json'} # 定義header資訊
payload = {
'format': 'pcm', # 以具體要識别的語音擴充名為準
'rate': 8000, # 支援8000或16000兩種采樣率
'channel': 1, # 固定值,單聲道
'token': token, # 上述擷取的token
'cuid': 'B8-76-3F-41-3E-2B', # 本機的MAC位址或裝置唯一識别标志
'len': org_voice_len, # 上述擷取的原始檔案内容長度
'speech': base64_voice_data # 轉碼後的語音資料
}
data = json.dumps(payload) # 将資料轉換為JSON格式
vop_url = '
http://vop.baidu.com/server_api' # 語音識别的API
voice_res = requests.post(vop_url, data=data, headers=headers) # 發送語音識别請求
api_data = voice_res.text # 獲得語音識别文字傳回結果
text_data = json.loads(api_data)['result']
print(api_data) # 列印輸出整體傳回結果
print(text_data) # 列印輸出語音識别的文字
代碼以空行作為分隔,包括4個部分:
第1部分為導入需要的庫資訊,具體用途見代碼注解。
第2部分為獲得要使用百度語音識别API的token資訊。其中的API_Key和Secret_Key見圖2-36。token_url通過占位符定義出完整字元串,并在請求時發送具體變量資料,從傳回的資訊中直接讀取token便于在下面應用中使用。有關擷取token的更多資訊,具體查閱
http://yuyin.baidu.com/docs/asr/56第3部分主要用于擷取和處理語音檔案資料。通過最常見的open方法以二進制的方式讀取語音資料,然後從獲得的語音資料中擷取原始資料長度,并将原始資料轉換為base64編碼格式。這裡需要注意的是,需要将其decode為utf-8格式的編碼,否則産生的結果對象為bytes類型,JSON會報解析錯誤“TypeError: Object of type 'bytes' is not JSON serializable”。
第4部分為本節内容的主體,發送請求擷取語音識别結果。本段落中先定義了發送頭資訊;然後定義了一個字典,用于存儲要發送的key-value字元串并将其轉換為JSON格式;接着通過post方法以隐式發送的方式進行上傳并獲得傳回結果;最後輸出傳回結果和其中的語音轉文字的資訊。該部分内容的細節比較多,具體參見百度語音API開發說明
http://yuyin.baidu.com/docs/asr/57關于cuid的擷取,由于筆者是在本地計算機上測試的,是以使用的是MAC位址。擷取MAC位址的方法是:打開系統終端指令行視窗(Win+R,輸入cmd并按Enter鍵),在指令行中輸入指令ipconfig/all,在列出的所有連接配接中找到其中媒體狀态不是“媒體已斷開”并且屬于目前連接配接的實體位址資訊,如圖2-37所示為筆者計算機MAC資訊。
有關語音服務的更多資訊,具體查閱
http://www.xfyun.cn上述代碼執行後傳回如下結果:
{"corpus_no":"6520028890940897658","err_msg":"success.","err_no":0,"result":["百度語音提供技術支援,"],"sn":"989585587221518062523"}
['百度語音提供技術支援,']
系統成功傳回識别結果,錄音的内容是“百度語音提供技術支援”。第2段的編碼是unicode編碼格式的中文。
總結:上述語音識别僅提供了關于語音轉文字的方法。其實語音本身包括非常多的資訊,除了相對淺層的生理和實體特征,例如語速、音調、音長、音色、音強等外,還包括更深層次的社會屬性,這部分内容需要自然語音了解的深層次應用。目前的語音資料讀取後主要應用方向包括:
- 語音轉文字。這也是廣義上語音識别的一種,直接将語音資訊轉為文字資訊,例如微信中就有這個小功能。
- 語音識别。語音識别指的是對說話者通過選取語音識别單元、提取語音特征參數、模型訓練、模型比對等階段,實作其角色識别和個體識别的過程,例如通過某段語音識别出是哪個人說的話。
- 語音語義了解。在語音識别的基礎上,需要對語義特征進行分析,目的是通過計算得到語音對應的潛在知識或意圖,然後提供對應的響應内容或方法。語音識别和語音了解的差異之處在于,語音識别重在确定語音表達的字面含義,屬于表層意義;而語音了解重在挖掘語音的背後含義,屬于深層意義。
- 語音合成。語音合成就是讓計算機能夠“開口說話”,這是一種拟人的技術方法。語音合成,又稱文本轉語音(Text to Speech)技術,它通過機械的、電子的方法将文字資訊轉變為人類可以聽得懂的語音。
- 應用內建。經過分析、識别後的資訊可以與硬體內建,直接通過語音發送指令。例如通過跟Siri(蘋果手機上的語音助理)的“溝通”,除了可以進行日常對話,還可以告訴你天氣情況、幫你設定系統日程、介紹餐廳等。這是智能機器人在模式識别方面的典型應用。
基于上述的複雜應用場景,通常語音後續分析、處理和模組化等過程都無法由資料工程師單獨完成,還需要大量的語料庫素材,以及社會學、信号工程、語言文法、語音學、自然語音處理、機器學習、知識搜尋、知識處理等交叉學科和相關領域才有可能解開其中的密碼。
2.4 本章小結
内容小結:本章的内容較多,主要涉及企業資料化營運可能産生資料的方方面面,包括資料來源的類型、通過不同方式獲得營運資料以及對非結構化資料的擷取等方面。不同的企業由于其行業和企業背景不同,通常不會全部覆寫其中的所有資料場景,讀者可根據自身情況和需求選擇。另外,大多數讀者所在的企業,應該以結構化的資料為主,内容延展中的知識作為課外補充和了解即可,真正到需要用到這些知識時,再學習和查閱更多資料。本書所有示例中的原始代碼,在“附件-chapter2”中的chapter2_code.ipynb中可以找到,同時在該檔案夾下存儲了所有示例用到的本地資料。
重點知識:本章需要讀者重點掌握2.2節所講的内容,這裡介紹了資料工作者常用的資料來源,其中從文本檔案讀取營運資料、從關系型資料庫MySQL讀取資料最為常用。
外部參考:由于資料來源的擷取與資料生産、采集、存儲、處理和挖掘工具息息相關,不同的系統和工具之間需要了解更多才有可能更好地利用資料。以下工具或知識是本書以及很多企業中都會用到的,希望讀者能進行更深入的學習。
- Google BigQuery:BigQuery可以作為雲服務應用,可以與幾乎所有的Google服務打通并将資料導入其中(當然也包括Google Analytics資料)。同時BigQuery還提供了BQML,即資料庫内的Machine Learning的功能,在資料庫中可以實作從查詢、模組化、檢驗到預測的整個資料分析和挖掘工作,是以BQML值得讀者一探究竟。
- Google Analytics API:Google Analytics幾乎是目前世界上最流行的流量采集和分析工具之一,它直接支援了多種類型的API,可以為使用者提供資料導入導出、查詢、賬戶管理等操作,包括報告API、實時API、meta API等,是Google Analytics資料分析的利器。配合Google BigQuery的hit(點選)級别/粒度的資料,可實作流量資料的二次深度發掘。
- SAS:做資料挖掘的讀者一般都會知道這個工具,SAS是資料挖掘和商業智能領域最為權威和流行的商用工具之一。該工具在很多大型企業内部都有應用,例如國家資訊中心、國家統計局、衛生部、中國科學院等,其專業能力可見一斑。
- SQL:作為關系型資料庫應用的核心,常用的查詢文法需要資料工作者掌握。除了用于關系型資料庫外,SQL也可以應用到大資料工作處理領域,例如HIVE、Spark SQL等。其通用性(當然需要做文法需要适當修改)使得SQL幾乎在各個企業都有用武之地。
- 正規表達式:本書在多個應用示例中都用到了正規表達式,尤其在非結構化資料工作領域,正規表達式幾乎是“标配”知識。
應用實踐:本章的内容屬于資料工作的第1步,是以希望讀者能熟悉不同的資料接入和讀取方法。每種資料來源類型建議讀者都逐一進行實踐,然後集中精力到現有工作或學習環境中,以熟練掌握擷取不同資料來源的方法和技巧。