件轉換工具新增exel轉html功能,可在線預覽excel。
1.打開工具,選擇excel文件
單sheet模式
2.轉換文件
單sheet模式
可以看到提供了頁數屬性單sheet和多sheet,默認為單sheet,該種模式下,轉換器會將excel里每個sheet頁轉換到一個html文件上,從上至下拼接起來,如下圖:
單sheet模式轉換文件
單sheet模式輸出文件
多sheet模式
該模式下轉換器會自動識別excel每個sheet頁,并將每個sheet輸出到html上對應tab頁上,可以點擊html上不同tab頁切換查看內容,如下圖。
多sheet模式輸出文件
多sheet模式輸出文件
工作生活中,經常會遇到excel文件需要在內部系統線上或線下發給其他人預覽,但是又不想其他人有編輯權限,我們一般會將excel文件轉圖片或轉pdf上傳系統,這里提供了一種新途徑直接轉html,瀏覽器可在線預覽,相關軟件工作人員也可開發相應的excel在線預覽功能。
exceljs是一個讀取,操作和編寫電子表格數據和樣式到XLSX和JSON,從Excel電子表格文件逆向工程設計的項目。之所以稱它最強,是因為它的功能強大,簡直就是專門為Excel打造的前端處理插件,到目前為止,筆者還尚未見過比這個更強大的前端插件,由于其強悍的前端處理能力,這就意味著有很多操作將減輕服務器端壓力,而且性能更加出色!
https://github.com/exceljs/exceljs
安裝我們當然是首選npm
npm install exceljs
var workbook = new Excel.Workbook();
workbook.creator = 'Me';
workbook.lastModifiedBy = 'Her';
workbook.created = new Date(1985, 8, 30);
workbook.modified = new Date();
workbook.lastPrinted = new Date(2016, 9, 27);
// 將工作簿日期設置為1904日期系統
workbook.properties.date1904 = true;
“工作簿”視圖控制Excel在查看工作簿時打開多少個單獨的窗口。
workbook.views = [
{
x: 0, y: 0, width: 10000, height: 20000,
firstSheet: 0, activeTab: 1, visibility: 'visible'
}
]
var sheet = workbook.addWorksheet('My Sheet');
用addWorksheet函數的第二個參數設置工作表的選項。
// 創建一個紅色標簽顏色的工作表
var sheet = workbook.addWorksheet('My Sheet', {properties:{tabColor:{argb:'FFC0000'}}});
// 創建一個隱藏網格線的工作表
var sheet = workbook.addWorksheet('My Sheet', {properties: {showGridLines: false}});
// 創建一個第一行和列凍結的工作表
var sheet = workbook.addWorksheet('My Sheet', {views:[{xSplit: 1, ySplit:1}]});
使用工作表id從工作簿中刪除工作表。
// 創建工作表
var sheet = workbook.addWorksheet('My Sheet');
// 使用工作表ID刪除工作表
workbook.removeWorksheet(sheet.id)
// 迭代所有sheet
// 注意:workbook.worksheets.forEach仍然可以工作,但這個方式更好
workbook.eachSheet(function(worksheet, sheetId) {
// ...
});
// 按名稱獲取表格
var worksheet = workbook.getWorksheet('My Sheet');
// 按ID獲取表格
var worksheet = workbook.getWorksheet(1);
。。。。。。以上只是部分文檔中的介紹,感興趣的小伙伴可以移步Github直接查看詳細的文檔,完整功能了解可參考下一個標題
PS:提供了中文文檔
雖然以上功能還不能包括了Excel的所有功能,但也已經相當的豐富了!
在之前的文章中曾介紹過另一個不錯的前端Excel插件,感興趣的可以去看一看,exceljs擁有這么豐富的功能,如果你想開發一個功能強大的Web電子表格,不妨多嘗試嘗試!
讀:本文要介紹的這些技法,會用Python讀入各種格式的數據,并存入關系數據庫或NoSQL數據庫。
作者:托馬茲·卓巴斯(Tomasz Drabas)
本文摘編自《數據分析實戰》,如需轉載請聯系我們
本文的源代碼與數據集都可在Github上獲取。如果要復制代碼庫,打開你的終端(Windows環境下的命令行、Cygwin或Git Bash,Linux/Mac環境下的Terminal),鍵入下面這條命令:
git clone https://github.com/drabastomek/practicalDataAnalysisCookbook.git
注意,你的機器得裝好Git了。安裝指南參見:
我們將使用一個數據集,包含985項真實的房產交易。這些交易是連續5天內在Sacramento發生的。數據下載自:
精確地說,來自:
數據已轉成多種格式,放在GitHub代碼庫的Data/Chapter01文件夾中。
另外,你會學到如何從HTML文件中檢索信息。出于這個目的,我們將使用Wikipedia上字母A打頭的機場列表:
我們將使用OpenRefine清理我們的數據集;它很擅長數據的讀取、清理以及轉換數據。
01 用Python讀寫CSV/TSV文件
CSV和TSV是兩種特定的文本格式:前者使用逗號分隔數據,后者使用\t符。這賦予它們可移植性,易于在不同平臺上共享數據。
1. 準備
要實踐這個技法,你要先裝好pandas模塊。這些模塊在Anaconda發行版Python中都有。如果你裝的是這個版本,就省事了。如果不是,那你得安裝pandas并確保正確加載。
可以從
下載Anaconda。
如果你裝了Python,沒有pandas,你可以從
下載,并按照文檔安裝到你的操作系統中。
此外沒有要求了。
2. 怎么做
pandas模塊提供了高性能的高級數據結構(比如DataFrame)以及一些基本的分析工具。
DataFrame是一種數據結構,有點像Excel表格,列代表數據集的維度(例如,人的身高和體重),行存儲著數據(例如,1000個人的具體身高和體重數據)。參考:
這個模塊提供了一些方法,便于讀取各種格式的數據。下面這小塊代碼讀取了CSV和TSV格式的數據,存入pandas DataFrame數據結構,然后寫回到磁盤上(read_csv.py文件):
import pandas as pd
# 讀出數據的文件名
r_filenameCSV = '../../Data/Chapter01/realEstate_trans.csv'
r_filenameTSV = '../../Data/Chapter01/realEstate_trans.tsv'
# 寫進數據的文件名
w_filenameCSV = '../../Data/Chapter01/realEstate_trans.csv'
w_filenameTSV = '../../Data/Chapter01/realEstate_trans.tsv'
# 讀取數據
csv_read = pd.read_csv(r_filenameCSV)
tsv_read = pd.read_csv(r_filenameTSV, sep='\t')
# 輸出頭10行記錄
print(csv_read.head(10))
print(tsv_read.head(10))
# 寫入文件
with open (w_filenameCSV, 'w') as write_csv:
write_csv.write(tsv_read.to_csv(sep=',', index=False))
with open(w_filenameTSV, 'w') as write_tsv:
write_tsv.write(csv_read.to_csv(sep='\t', index=False))
打開命令行控制臺(Windows環境下可使用命令或Cygwin,Linux/Mac環境下可使用Terminal),執行這條命令:
python read_csv.py
你會看到類似這樣的輸出:
| Baths | beds | | city | latitude | longitude | price |
| 0 | 1 | 2 | SACRAMENTO | 38.631913 | -121.434879 | 59222 |
| 1 | 1 | 3 | SACRAMENTO | 38.478902 | -121.431028 | 68212 |
| 2 | 1 | 2 | SACRAMENTO | 38.618305 | -121.443839 | 68880 |
…
3. 原理
首先加載pandas,以使用DataFrame及相關方法來讀寫數據。注意,關鍵詞as賦給pandas一個別名pd。這樣在后面的代碼中,使用DataFrame或read_csv(...)方法時,我們就不用寫出包的全名了。我們將(用于讀和寫的)文件名分別存于變量r_filenameCSV(TSV)和w_filenameCSV(TSV)。
使用pandas的read_csv(...)方法讀取數據。這個方法用途很廣,接受一系列輸入參數。但有一個參數是必需的,一個文件名或緩沖區,也就是一個打開的文件對象。要解析realEstate_trans.tsv文件,你要指定sep=‘\t’參數;默認情況下,read_csv(...)方法會推斷文件使用的分隔符,不過我可不喜歡碰運氣式編程,向來是指定分隔符的。
兩個文件中的數據一模一樣,所以你可以輸出一些記錄,看看文件是否正確讀入。這可通過對DataFrame對象應用.head(<no_of_rows>)方法達成,其中<no_of_rows>指的是要輸出的行數。
將數據存于pandas DataFrame對象意味著,數據的原始格式并不重要;一旦讀入,它就能保存成pandas支持的任何格式。在前面這個例子中,我們就將CSV文件中讀取的內容寫入了TSV文件。
無論讀寫,打開文件都要使用with open(…) as …:這個固定搭配。這種方式的優點在于,一旦完成了讀寫任務,即使由于某些原因拋出了異常,文件依然會正確關閉。
異常是指程序員寫代碼時期望之外的情況。
例如,假設你有一個文件,每行只包含一個數字:你打開這個文件,開始讀取。每一行作為文本讀入,你需要將文本轉為一個整數——計算機可以將其作為數字理解(并處理)的數據結構,而非文本。
當數據中只有數字時一切安好。然而,你將會認識到,我們收集的數據在某些方面是有瑕疵的,那么,某些行包含一個字母而非數字時,文本到整數的轉換會失敗,而Python會拋出一個異常。
open(<filename>, ‘w’)會以寫模式(w參數)打開<filename>指定的文件。也可以傳入’r’指定以讀模式打開文件。以’r+’模式打開文件允許數據的雙向流動(讀取和寫入),這樣你就可以在需要時往文件的末尾附加內容。你也可以指定rb或wb來處理二進制數據(而非文本)。
to_csv(…)方法將DataFrame的內容轉換為可存儲于文本文件的格式。你要指定分隔符,比如sep=‘,’,以及是否保存DataFrame的索引,默認是保存的。我們不希望存,所以要指定index=False。
用索引可以很方便地辨認、校準、訪問DataFrame中的數據。索引可以是一列連續的數字(就像Excel中的行號)或日期;你還可以設定多列索引。索引列并不是數據(即便打印DataFrame對象時你會在屏幕上看到索引)。
要了解更多關于索引的內容,可訪問:
4. 更多
這里介紹讀寫CSV、TSV文件最方便最快捷的方法。如果你不想把數據存于pandas的DataFrame數據結構,你可以使用csv模塊。像下面這樣讀取文件(read_csv_alternative.py文件):
import csv
# 讀入數據的文件名
r_filenameCSV = '../../Data/Chapter01/realEstate_trans.csv'
r_filenameTSV = '../../Data/Chapter01/realEstate_trans.tsv'
# 保存數據的數據結構
csv_labels = []
tsv_labels = []
csv_data = []
tsv_data = []
# 讀取數據
with open(r_filenameCSV, 'r') as csv_in:
csv_reader = csv.reader(csv_in)
# 讀取第一行,這是列標簽
csv_labels = csv_reader.__next__()
# 遍歷記錄
for record in csv_reader:
csv_data.append(record)
with open(r_filenameTSV, 'r') as tsv_in:
tsv_reader = cvs.reader(tsv_in, delimiter='\t')
tsv_labels = tsv_reader.__next__()
for record in tsv_reader:
tsv_data.append(record)
# 打印標簽
print(csv_labels, '\n')
print(tsv_labels, '\n')
# 打印頭10行記錄
print(csv_data[0:10], '\n')
print(tsv_data[0:10], '\n')
我們將標簽和數據分別存儲于csv(tsv)_labels和csv(tsv)_data兩個列表。.reader(…)方法從文件中逐行讀取數據。要創建.reader(…)對象,你要傳入一個打開的CSV或TSV文件對象。另外,要讀入TSV文件,你也得像DataFrame中一樣指定分隔符。
csv模塊也提供了csv.writer對象,可將數據以CSV/TSV格式存儲。參見csv模塊的文檔:
5. 參考
查閱pandas文檔中講解reader_csv(…)和write_csv(…)的部分,了解更多可傳入的參數。文檔位于:
02 用Python讀寫JSON文件
JSON的全稱是JavaScript Object Notation。這是個嵌套的、類似字典的結構,以逗號為分隔符,存儲鍵值對;鍵與值之間以冒號分隔。JSON格式獨立于具體平臺(就像XML,我們將在 用Python讀寫XML文件介紹),便于平臺之間共享數據。
要深入了解JSON,可參考:
1. 準備
要實踐這個技法,你要先裝好pandas模塊。此外沒有要求了。
2. 怎么做
下面是讀取JSON文件的代碼。注意,我們假設已經引入了pandas模塊,并以別名pd指代(read_json.py文件):
# 讀出數據的JSON文件
r_filenameJSON = '../../Data/Chapter01/realEstate_trans.json'
# 讀取數據
json_read = pd.read_json(r_filenameJSON)
# 打印頭10行記錄
print(json_read.head(10))
3. 原理
這段代碼與前一節的類似。首先,指定JSON文件的名字——我們將其存于r_filenameJSON字符串中。然后,使用pandas的read_json(…)方法,傳入r_filenameJSON。
讀出的數據存儲于json_read這一DataFrame對象。進而使用.tail(…)方法打印出最后10條數據。要寫入一個JSON文件,你可以對DataFrame使用.to_json()方法,將返回的數據寫進一個文件,類似用Python讀寫CSV/TSV文件中介紹的流程。
4. 更多
也可以使用json模塊來讀寫JSON文件。可以使用下面的代碼從JSON文件中讀取數據(read_json_alternative.py文件):
# 讀取數據
with open('../../Data/Chapter01/realEstate_trans.json', 'r') as json_file:
jsonread = json.loads(json_file.read())
這段代碼將realEstate_trans.json文件中讀出的數據存入json_read列表。這里對文件使用了.read()方法,將文件內容全部讀入內存。下面的代碼將數據存儲于一個JSON文件:# 寫回到文件中
with open('../../Data/Chapter01/realEstate_trans.json', 'w') as json_file:
json_file.write(json.dumps(json_read))
5. 參考
參閱pandas文檔中read_json的部分。文檔位于:
03 用Python讀寫Excel文件
以表格形式操作數據的文件格式中,Microsoft的Excel文件可以說是最流行的了。拿最新的XLSX格式來說,Excel可以在單個工作表中存儲一百多萬行及一萬六千多列。
1. 準備
要實踐這個技法,你要先裝好pandas模塊。此外沒有要求了。
2. 怎么做
下面是讀取JSON文件的代碼。注意,我們假設已經引入pandas模塊,并以pd指代(read_xlsx.py文件):
# 讀寫數據的文件名
r_filenameXLSX = '../../Data/Chapter01/realEstate_trans.xlsx'
w_filenameXLSX = '../../Data/Chapter01/realEstate_trans.xlsx'
# 打開Excel文件
xlsx_file = pd.ExcelFile(r_filenameXLSX)
# 讀取內容
xlsx_read = {
sheetName: xlsx_file.parse(sheetName) for sheetName in xlsx_file.sheet_names
}
# 打印Sacramento頭10份價格
print (xlsx_read['Sacramento'].head(10)['price'])
# 寫入Excel文件
xlsx_read['Sacramento'].to_excel (w_filenameXLSX, 'Sacramento', index=False)
3. 原理
類似之前的例子。用pandas的ExcelFile(...)方法打開XLSX文件,并賦給xlsx_file對象。用.parse(...)方法讀取指定工作表的內容,并存儲于xlsx_read字典。注意,通過ExcelFile對象的.sheet_names屬性,你可以訪問Excel文件中的所有工作表。
創建xlsx_read字典時,我們使用了字典表達式,這個做法很Python:不是顯式地遍歷工作表,將元素添加到字典,而是使用字典表達式,讓代碼更可讀、更緊湊。
表達式效仿數學上的表示方法,這讓代碼更容易理解。比方說,2的冪次的列表:(A = (2^0, 2^1, 2^2, …, 2^8) = (2^x: 0 <= x < 9), x取整數)。使用表達式很容易轉成Python代碼:A = [2**x for x in range(0, 9)]。就創建了這樣的列表:A = [1, 2, 4, 8, 16, 32, 64, 128, 256]。
另外,Python里,表達式也比顯式的循環要快那么一點點。
range(<from>, <to>)函數生成了從<from>到<to>-1的一列整數。例如,range(0, 3)生成的序列是0,1,2.
存儲數據到Excel文件中也很簡單。僅需調用.to_excel(...)方法,第一個參數傳你要保存數據的文件名,第二個參數傳工作表的名字。在我們的例子中,我們還指定了index=False,這樣不會保存索引;默認情況下,.to_excel(...)方法保存A列的索引。
4. 更多
讀取Excel文件,除了用pandas的read_excel(...)方法,你也可以選擇其它Python模塊。pandas使用xlrd讀取數據并轉成DataFrame。
對于XLSX文件,你也可以使用openpyxl模塊(read_xlsx_alternative.py文件):
import openpyxl as oxl
# 讀出數據的文件名
r_filenameXLSX = '../../Data?Chapter01/realEstate_trans.xlsx'
# 打開Excel文件
xlsx_wb = oxl.load_workbook(filename=r_filenameXLSX)
# 工作簿中所有工作表的名字
sheets = xlsx_wb.get_sheet_names()
# 提取'Sacramento'工作表
xlsx_ws = xlsx_wb[sheets[0]]
首先,讀取Excel文件,存入xlsx_wb(工作簿)。從工作簿中提取所有工作表的名字,并存入sheets變量。這里我們的工作簿中只有一個工作表,所以sheets變量就等于'Sacramento'。我們用它創建一個xlsx_ws對象,以遍歷所有的行:
labels = [cell.value for cell in xlsx_ws.rows[0]]
data = [] # 保存數據的列表
for row in xlsx_ws.rows[1:]:
data.append([cell.value for cell row])
第一行是所有列的標簽,最好還是單獨存儲——我們放到labels變量中。進而使用.rows迭代器,遍歷工作表中每一行,將所有單元格中的數據加入data列表:
print (
[item[labels.index('price')] for item in data[0:10]]
)
代碼最后打印出頭10行的房屋價格。我們使用表達式生成價格的列表。如代碼所示,對于列表對象,你可以調用.index(...)方法查找某一元素首次出現的位置。
5. 參考
http://pandas.pydata.org/pandas-docs/stable/io.html#io-excel
另外,你可以訪問
找到一系列模塊,可幫你處理.xls和.xlsx等Excel文件格式。
04 用Python讀寫XML文件
XML的全稱是eXtensible Markup Language(擴展標記語言)。盡管不像前面介紹的格式那樣流行,不少網絡API還是支持XML編碼的。
XML文檔結構類似一棵樹。讀取內容時,我們首先訪問根節點(通常來說,這個節點后面會跟著XML的聲明<?xml version="1.0" encoding="UTF-8"?>;每個XML文檔都要以這樣的聲明開頭)。在我們的例子中,根節點是<records>。一個<record>...</record>中包含了一系列<var var_name=...>...</var>。
當心:xml模塊不安全。處理未知來源的XML消息時必須得小心。攻擊者可能訪問本地文件,發動DoS攻擊等等。
xml模塊的文檔參見:
1. 準備
要實踐這個技法,你要先裝好pandas和xml模塊。此外沒有要求了。
2. 怎么做
從XML文件直接向一個pandas DataFrame對象讀入數據需要些額外的代碼:這是由于XML文件有特殊的結構,需要針對性地解析。接下來的章節,我們會詳細解釋這些方法。源代碼可在read_xml.py文件中找到:
import pandas as pd
import xml.etree.ElementTree as ET
def read_xml(xml_tree):
'''
讀入XML數據,返回pd.DataFrame
'''
def iter_records(records):
'''
遍歷所有記錄的生成器
'''
def write_xml(xmlFileName, data):
'''
以XML格式保存數據
'''
def xml_encode(row):
'''
以特定的嵌套格式將每一行編碼成XML
'''
# 讀出和寫入數據的文件名
r_filenameXML = '../../Data/Chapter01/realEstate_trans.xml'
w_filenameXML = '../../Data/Chapter01/realEstate_trans.xml'
# 讀取數據
xml_read = read_xml (r_filenameXML)
# 打印頭10行記錄
print (xml_read.head(10))
# 以XML格式寫回到文件
write_xml(w_filenameXML, xml_read)
3. 原理
我們一步步分析前面的代碼。首先引用需要的模塊。xml.etree.ElementTree是一個輕量級XML解析器,我們用它來解析文件的XML結構。和之前一樣,分別將讀取和寫入的文件名定義為變量(r_filenameXML,w_filenameXML)。
使用read_xml(...)方法從XML文件讀取數據:
def read_xml(xmlFileName):
with open(xmlFileName, 'r') as xml_file:
# 讀取數據,以樹的結構存儲
tree = ET.parse(xml_file)
# 訪問樹的根節點
root = tree.getroot()
# 返回DataFrame
return pd.DataFrame(list(iter_records(root)))
這個方法只消傳入文件名這一個參數。首先,打開文件。使用.parse(...)方法,我們由XML文件創建了一個樹狀結構并存入tree對象。接著,在tree對象上用.getroot()方法提取根節點:這是進一步處理數據的前提。最后一行調用iter_records方法,傳入根節點的引用,進而將返回的信息轉換成DataFrame:
def iter_records(records):
for record in records:
# 保存值的臨時字典
temp_dict = {}
# 遍歷所有字段
for var in record:
temp_dict[
var.attrib['var_name']
] = var.text
# 生成值
yield temp_dict
iter_records方法是一個生成器:顧名思義,這個方法生成一些值。普通方法結束時(return語句)一次性返回所有的值;生成器不同,每次只向調用方返回一個值(即yield關鍵字),直到結束。
更深入地討論生成器,建議閱讀
我們的iter_records方法,每讀入一行,就返回一個temp_dict字典對象給read_xml方法。字典中每個元素的鍵名對應XML中<var>元素的var_name屬性。(<var>有這樣的格式:<var var_name=...>。)
<var>標簽可能有其它名字的屬性——這些屬性會存在.attrib字典(XML樹節點一個屬性)并通過各自的名字訪問——參考代碼中高亮的部分。
<var>的值(<var>...</var>內的部分)可通過XML節點的.text屬性訪問,而.tag屬性存儲其名字(這個例子中就是var)。
read_xml方法的return語句從傳入的所有字典中創建一個列表,轉換成DataFrame。
我們使用write_xml(...)方法,以XML格式寫入數據:
def write_xml (xmlFileName, data):
with open (xmlFileName, 'w') as xmlFile:
# 寫頭部
xmlFile.write(
'<?xml version="1.0" encoding="UTF-8"?>\n'
)
xmlFile.write('<records>\n')
# 寫數據
xmlFile.write(
'\n'.join(data.apply(xml_encode, axis=1))
)
# 寫尾部
xmlFile.write('\n</records>')
這個方法打開xmlFileName參數指定的文件。每個XML文件需要以XML聲明開頭(參考本技法的導論)。接著,我們寫了XML schema的根節點,<records>。
接下來就是寫數據。使用DataFrame對象的.apply(...)方法遍歷內部每一行。第一個參數指定了要應用到每行記錄上的方法。axis參數的默認值為0。意味著指定的方法會應用到DataFrame的每一列上。指定為1,我們讓.applay(...)方法將指定的xml_encode(...)方法應用到DataFrame的每一行上。使用xml_encode(...)方法處理data DataFrame的每一行:
def xml_encode(row):
# 第一步——輸出record節點
xmlItem = ['<record>']
# 第二步——給行中每個字段加上XML格式<field name=…>…</field>
for field in row.index:
xmlItem \
.append(
' <var var_name=“{0}”>{1}</var>' \
.format (file, row[field])
)
# 最后一步——標記record節點的結束標簽
xmlItem.append('</record>')
# 返回一個字符串
return '\n'.join(xmlItem)
代碼生成了一個字符串列表,xmlItem。列表的首元素是<record>,尾元素是</record>。對行中每個字段,我們以<var var_name=<column_name>><value></var>的格式封裝,并加進字符串列表。加粗部分指的是列名(<column_name>)和對應的值(<value>)。
解析完所有字段后,使用'\n'.join(...)方法,將xmlItem列表中所有項連接成一個長字符串。<var>...</var>標簽之間以\n分隔。這個字符串被返回給調用方(write_xml)。記錄在write_xml(...)方法中進一步連接,并輸出到文件。最后加上閉合標簽</records>,大功告成。
05 用pandas解析HTML頁面
盡管以前面介紹的格式保存數據是最常見的,我們有時還是要在網頁表格中查找數據。數據的結構通常包含在<table> </table>標簽內。本技法會介紹如何從網頁獲取數據。
1. 準備
要實踐這個技巧,你要先裝好pandas和re模塊。re是Python的正則表達式模塊,我們用它來清理列名。另外,使用pandas 的read_html(...)方法要預裝html5lib模塊。如果你使用的是Anaconda發行版Python,使用下面的命令就可以:
conda install html5lib
如果不是,你可以從
下載源代碼。解壓,手動安裝模塊:
cd html5lib-python-parserpython setup.py install
此外沒有要求了。
2. 怎么做
pandas可以很方便地訪問、提取、解析HTML文件。兩行代碼就能搞定。retrieve_html.py可不止兩行,這些我們下一環節再討論:
# 要調用的url
url = 'https://en.wikipedia.org/wiki/' + \
'List_of_airports_by_IATA_code:_A'
# 從HTML提取數據
url_read = pd.read_html (url, header = 0)[0]
3. 原理
pandas 的read_html(...)方法解析HTML文件的DOM結構,從所有table節點中提取數據。第一個參數可以是URL、文件或HTML標簽原始字符串。第二個參數指定header = 0,忽略了表頭。
read_html(...)方法返回了一個DataFrame對象的列表,每項對應于HTML文件中一個table。Wikipedia的機場頁面只包含了一個table,所以我們只要取DataFrame列表的首元素。是的,就是這樣!機場列表已經在url_read對象中了。
拿到的數據還有兩點瑕疵:列名包含空白字符,數據包含分隔行。對于名字中可能包含多種空白字符(空格符、制表符等)的問題,我們使用re模塊:
import re
# 匹配字符串中任意空白字符的正則表達式
space = re.compiler(r'\s+')
def fix_string_spaces (columnsToFix):
'''
將列名中的空白字符換成下劃線
'''
tempColumnNames = [] # 保存處理后的列名
# 循環處理所有列
for item in columnsToFix:
# 匹配到
if space.search (item):
# 處理并加入列表
tempColumnNames \
.append('_'.join (space.split (item)))
else:
# 否則直接加入列表
tempColumnNames.append (item)
return tempColumnNames
首先,編譯那個匹配出至少一個空白字符的正則表達式。
對正則表達式的詳細討論超出了本書的知識范圍。關于這個主題,有個知識手冊寫得挺好的:
或者參考re模塊的文檔:
然后循環處理列,找到空白字符(space.search(...))時,將列名拆開(space.split(...))存入列表。以’_’為間隔,連接列表元素。如果不含空白字符,就將原始列名加入列表。使用下面這行代碼處理DataFrame中的列名:
url_read.columns = fix_string_spaces (url_read.columns)
查看Wikipedia上的機場表,你會發現它根據前兩個字母分組,組與組之間有分隔行。分隔行中缺失了其它列。為了處理這個問題,我們使用DataFrame的.dropna (...)方法。
pandas有多種方法用于處理NaN(Not a Number)情況。估算缺失值會介紹.fillna (...)方法。
.dropna (...)方法刪掉缺少任意字段數據的行(或者列)。調用.dropna (...)時很容易不傳任何參數,這樣即便是合理的行,只要缺了夏時制(Daylight Saving Time, DST)或國際民航組織機場代碼,也會被刪掉。我們可以設道門檻。
粗粗瀏覽下數據可以發現,有些合理的行最多會缺兩個字段。參數inplace=True直接在原來的DataFrame對象上移除數據,而非復制出一個DataFrame、清理后再返回;默認值是inplace=False:
url_read.dropna (thresh=2, inplace=True)
移除一些行后,DataFrame的索引會產生空洞??梢允褂眠@行代碼:
url_read.index = range (0, len(url_read))
下面這行代碼輸出頭10行IATA代碼及對應的機場名:
print (url_read.head (10)[['IATA', 'Airport_name']])
如果想取出不止一列,可以以列表的形式傳入;在我們的例子中,就是['IATA', 'Airport_name']。下面的代碼是等效的:
print (url_read[0:10] [['IATA', 'Airport_name']])
關于作者:托馬茲·卓巴斯(Tomasz Drabas)微軟數據科學家,致力于解決高維特征空間的問題。他有超過13年的數據分析和數據科學經驗:在歐洲、澳大利亞和北美洲三大洲期間,工作領域遍及高新技術、航空、電信、金融和咨詢。
本文摘編自《數據分析實戰》,經出版方授權發布。
延伸閱讀《數據分析實戰》
推薦語:通過大量的現實案例,詳細講解數據分析相關的各種方法。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。