一文貫通python文件讀取
不論是數(shù)據(jù)分析還是機器學(xué)習(xí),乃至于高大上的AI,數(shù)據(jù)源的獲取是所有過程的入口。 數(shù)據(jù)源的存在形式多為數(shù)據(jù)庫或者文件,如果把數(shù)據(jù)看做一種特殊格式的文件的話,即所有數(shù)據(jù)源都是文件。獲得數(shù)據(jù),就是讀取文件的操作,文件有各種各樣的格式即數(shù)據(jù)的組織形式,如何方便快捷地獲取文件中的內(nèi)容呢?
還是那句名言,life is short, just use python。
操作基礎(chǔ)
在python 中,文件的操作分為面向目錄和面向文件的,本質(zhì)都是一樣的。
面向目錄的常見操作見下表:
面向文件的常見操作見下表:
在這些基本操作中,遍歷目錄并列出所有文件或者所需的目標(biāo)文件是一種常見的操作。另外,需要注意的是打開文件時的模式,a,w,r,組合時的a+,w+,r+, 還有針對這六種模式在讀取二進制文件時都要加上b。 在操作結(jié)束時,一定要顯式關(guān)閉文件, 當(dāng)然 通過with 語句的隱式關(guān)閉也是可以的。
對于作為數(shù)據(jù)內(nèi)容源的文件而言, 可以簡單的分為文本和非文本兩類,就是內(nèi)容本身是文字的和非文字的,對混合形式的文件一般可以采用分而治之的方式。對于數(shù)據(jù)分析而言,這里側(cè)重于文件讀取及數(shù)據(jù)的采集上。
文本文件讀取
數(shù)據(jù)分析乃至文本分析都有涉及到文本文件的讀取。文本文件也可以粗略的分為兩類:純內(nèi)容文本和帶格式約定的文本。純內(nèi)容文本就是相對純粹的文本數(shù)據(jù),例如新聞,博客文字內(nèi)容,readme等等。帶格式約定的文本是為了增強內(nèi)容的功能性或者實現(xiàn)特定的語義,例如xml,html,json文件等。
純內(nèi)容文本文件
在讀取純內(nèi)容文本的時候,就是一般的讀文件基礎(chǔ)操作,需要注意的是文本內(nèi)容的字符集編碼。判斷文本文件屬于哪個字符集,老碼農(nóng)還在用chardet,不知道現(xiàn)在有沒有更先進的手段了。示例代碼如下:
- import chardet
- f = open('/target_path/abel.txt',r)
- my_data = f.read()
- print chardet.detect(my_data)
chardet.detect 返回的是一個字典,包括編碼類型和一個概率值。然后,就可以根據(jù)自己的需要進行編碼轉(zhuǎn)換了。
鍵值對相關(guān)的配置文件
在應(yīng)用中經(jīng)常有.ini文件來用于配置信息,在python 中可以利用ConfigParser來處理。ConfigParser 模塊有RawConfigParser,ConfigParser 和SafeConfigParser 三種對象,一般采用ConfigParser即可。 一個應(yīng)用的配置文件"myweb_config.ini"如下:
- [myweb]
- url = http://%(host)s:%(port)s/myweb
- host = 192.168.1.100
- port = 8888
那么,使用ConfigParser的示例代碼如下:
- import ConfigParser
- mysql_config = ConfigParser.ConfigParser()
- cf.read("myweb_config.ini")
- print cf.get("portal", "url")
讀取配置文件的一個常見使用情形是獲取數(shù)據(jù)庫的訪問信息,以便從數(shù)據(jù)庫中獲取數(shù)據(jù)。
Json,XML和HTML文件
JSON是一種輕量級的數(shù)據(jù)交換格式。Json 文件采用完全獨立于編程語言的文本格式來存儲和表示數(shù)據(jù)。簡潔和清晰的層次結(jié)構(gòu)使得 JSON 成為理想的數(shù)據(jù)交換語言,是當(dāng)前應(yīng)用中主流的數(shù)據(jù)文件之一。 通過Python的json模塊,可以將字符串形式的json數(shù)據(jù)轉(zhuǎn)化為字典,也可以將Python中的字典數(shù)據(jù)轉(zhuǎn)化為字符串形式的json數(shù)據(jù)。讀取Json文件的示例代碼如下:
- import json
- f = open("test.json", encoding='utf-8')
- my_json = json.load(f)
然后就可以對my_json 以字典方式進行讀取了,需要主要的是設(shè)置Json文件解碼模式。
XML是一套定義語義標(biāo)記的規(guī)則,將文檔分成許多部分并對這些部分加以標(biāo)識。同時,也是定義了用于定義其他與特定領(lǐng)域有關(guān)的、語義的、結(jié)構(gòu)化的標(biāo)記語言的句法語言。在python 中解析 XML 文件有三種方法:SAX,DOM,和ElementTree。ElementTree就像一個輕量級的DOM,示例代碼如下:
- import xml.etree.ElementTree as ET
- my_xml_tree = ET.parse('/home/abel/face.xml')
- print my_xml_tree.getroot()
HTML 更是我們最常接觸文件,基于web的數(shù)據(jù)爬蟲,數(shù)據(jù)分析,數(shù)據(jù)挖掘等都會涉及到HTML文件的讀寫。在python中,用BS4 來對html 進行操作是非常方便的,同樣也可以對xml 文件進行類似的操作,尤其是從網(wǎng)絡(luò)中讀取html,示例代碼如下:
- import requests
- from bs4 import BeautifulSoup
- res = requests.get("http://a.b.c/c?d=e")
- soup = BeautifulSoup(res.text)
- print soup.find_all('a')
CSV文件
CSV文件就是一種由逗號隔開的文本文件,使用非常廣泛,尤其是excel 文件可以另存為CSV文件,使分析CSV文件中的數(shù)據(jù)更加方便。 在Python中可以之間使用csv模塊進行操作即可,示例代碼如下:
- import csv
- csv_reader = csv.reader(open('mydata.csv', encoding='utf-8'))
- for each_line in csv_reader:
- print each_line
常見的文本文件除了純文本,鍵值對文件,json,xml,html,csv以外,就是大量的日志文件了,也可以選擇的相關(guān)庫或者自行分析讀取, 進一步就可能進入到NLP的領(lǐng)域了。
媒體文件讀取
媒體文件中的數(shù)據(jù)內(nèi)容一般不是文本,是經(jīng)過編碼是數(shù)據(jù),例如圖片,音頻,以及視頻文件,為了簡化可以暫不考慮其中的字幕情況。
圖片文件
圖片由各種各樣的格式即數(shù)據(jù)內(nèi)容的編解碼方式,在python 中一般使用PIL 庫對圖片文件進行讀取或者進一步的處理,示例代碼如下:
- from PIL import Image
- im = Image.open('/home/abel/abc.jpg')
- w, h = im.size
- im.thumbnail((w/2, h/2))
- im.save('/home/abel/abc_thumbnail.jpg', 'jpeg')
這個一個獲取一個圖片文件縮略圖的小例子。 PIL是很強大的,提供了幾乎所有的圖像基本操作,例如改變圖像大小,旋轉(zhuǎn)圖像,圖像格式轉(zhuǎn)換,色場空間轉(zhuǎn)換,圖像增強,直方圖處理,插值和濾波等等。當(dāng)然,其他的一些科學(xué)計算庫也提供了很多圖像處理的功能,例如大名鼎鼎的OpenCV, 具體可以參見《7行python代碼的人臉識別》一文。
音頻MP3
和圖片文件一樣, 音頻文件的編解碼格式同樣很多。以MP3為例,只要了解了MP3文件的編碼格式,就可以通過Python直接對MP3中的文件信息進行讀取了。如果不重復(fù)造輪子的話,python 對音頻的支持庫也有很多。就MP3而言,可以使用python 中的eye3D(http://http://eyed3.nicfit.net) 庫來讀取MP3 中的相關(guān)信息, 示例代碼如下:
- import eyed3
- f_mp3 = eyed3.load("/users/hecom/xiangwang.mp3")
- print f_mp3.tag.title
- print f_mp3.info.time_secs
技術(shù)演進日新月異,老碼農(nóng)曾經(jīng)使用過的PyMedia 好像很久沒人維護了,至于mp3 文件的播放,可以使用的庫同樣很多,例如mp3play,pyaudio以及pygame等。對于音頻文件的進一步處理一般就要涉及的語音識別和語音合成了。
視頻MP4
視頻可以粗略地看成音頻、圖片乃至文字的混合體了。在Python 中讀取并處理視頻文件,一般可以使用MoviePy庫(https://github.com/Zulko/moviepy)。MoviePy是可用于視頻編輯的基本操作(像剪切,合并,插入標(biāo)題),視頻合成(又名非線性編輯),視頻處理,或者創(chuàng)建高級的效果。它可以讀取和寫入的最普通的視頻格式,包括GIF。 示例代碼如下:
- from moviepy.editor import *
- video = VideoFileClip("mybaby.mp4").subclip(50,60)
- txt_clip = ( TextClip("My Son 2002",fontsize=70,color='white')
- .set_position('center')
- .set_duration(10) )
- result = CompositeVideoClip([video, txt_clip])
- result.write_videofile("mybaby_edited.mp4",fps=25)
這個小例子是將一個MP4提取其中50秒至60秒之間的數(shù)據(jù)并增加上一點文本信息生成一個新的MP4文件。MoviePy中提供了很多視頻處理的方法和示例,并且能與PIL,OpenCV,scikit Image,matplotlib等混合使用。另外,關(guān)于視頻的攝取,python中也是有vediocapture庫的。
帶格式編碼的文檔讀取
我們常見的另一類文檔如PDF,word,excel等也是一種混合文檔,里面一般以文本為主,主要在顯示方式上作了規(guī)則限定,文檔中包含了關(guān)于顯示格式的大量信息。當(dāng)然,這些文檔還可以嵌入媒體文件。粗淺地解釋一下,為了理解的方便,可以把這些帶格式編碼的文檔看作瀏覽器和html文本的結(jié)合體,這樣文件中的某些邏輯處理就可以想象成JavaScript的相關(guān)操作了。
PDF文件
PDF是一種非常好用的格式,它能夠解析并顯示與圖片結(jié)合在一起的文本,并且具備一般性的不可編輯。在Python 中一般可以通過pdfminer(http://www.unixuser.org/~euske/python/pdfminer/) 或者pypdf 來讀取pdf文件中的內(nèi)容, 官網(wǎng)給出的示例代碼如下:
- from pdfminer.pdfparser import PDFParser
- from pdfminer.pdfdocument import PDFDocument
- from pdfminer.pdfpage import PDFPage
- from pdfminer.pdfpage import PDFTextExtractionNotAllowed
- from pdfminer.pdfinterp import PDFResourceManager
- from pdfminer.pdfinterp import PDFPageInterpreter
- from pdfminer.pdfdevice import PDFDevice
- # Open a PDF file.
- fp = open('mypdf.pdf', 'rb')
- # Create a PDF parser object associated with the file object.
- parser = PDFParser(fp)
- # Create a PDF document object that stores the document structure.
- # Supply the password for initialization.
- document = PDFDocument(parser, password)
- # Check if the document allows text extraction. If not, abort.
- if not document.is_extractable:
- raise PDFTextExtractionNotAllowed
- # Create a PDF resource manager object that stores shared resources.
- rsrcmgr = PDFResourceManager()
- # Create a PDF device object.
- device = PDFDevice(rsrcmgr)
- # Create a PDF interpreter object.
- interpreter = PDFPageInterpreter(rsrcmgr, device)
- # Process each page contained in the document.
- for page in PDFPage.create_pages(document):
- interpreter.process_page(page)
除此之外,還可以采用命令行———— pdf2txt 直接調(diào)用pdf文件進行文本轉(zhuǎn)換。
word 文件
word文檔幾乎是最常見的辦公文件了,但是.docx文件的結(jié)構(gòu)比較復(fù)雜,一般分為三層:
- Docment對象表示整個文檔;
- Docment包含了Paragraph對象的列表,Paragraph對象用來表示文檔中的段落;
- 一個Paragraph對象包含Run對象的列表。
在python中 一般可以采用python-docx 庫對word文件進行讀寫,簡化起見,如果只關(guān)心word文件中的文本信息的話,示例代碼如下:
- import docx
- doc = docx.Document('/home/abel/test.docx')
- paras = doc.paragraphs
- text_in_doc =[]
- for each_p in paras:
- text_in_doc.append(each_p.text)
Python DocX目前是Python OpenXML的一部分,可以用它打開Word 2007及以后的文檔,而用它保存的文檔可以在Microsoft Office 2007/2010, Microsoft Mac Office 2008, Google Docs, OpenOffice以及Apple iWork 08中打開。
Excel 文件
python處理excel文件主要的第三方庫有xlrd、xlwt、xluntils和pyExcelerator等,還有人在這之上封裝了很多更方便實用的庫。這里使用樸實的xlrd(https://github.com/python-excel/xlrd/)來讀取excel文件,示例代碼如下:
- import xlrd
- myworkbook = xlrd.open_workbook('test.xls') # 打開xls文件
- table = myworkbook.sheet_by_name(u'Sheet1')
- nrows = table.nrows
- for i in range(nrows):
- print table.row_values(i)[:10]
這個小例子讀取了test.xls 文件,打印出來Sheet1中各行的前十列。xlrd 是有局限的,無法讀取excel中的一些對象,如:
- 圖表,圖片,宏以及其他的嵌入對象
- VBA,超鏈接,數(shù)據(jù)驗證
- 公式(結(jié)果除外),條件的格式化,注釋等等
好在,我們關(guān)注的是excel中的數(shù)據(jù)內(nèi)容,以便進行數(shù)據(jù)分析,這些局限無傷大雅。
一句話小結(jié)
文件數(shù)據(jù)源的讀取是數(shù)據(jù)分析的入口,使用Python可以方便快捷地讀取各種文件格式中的內(nèi)容,為進一步的數(shù)據(jù)分析或者數(shù)據(jù)清洗提供了簡潔方式。
【本文來自51CTO專欄作者“老曹”的原創(chuàng)文章,作者微信公眾號:喔家ArchiSelf,id:wrieless-com】