摘要:如果該文件已存在,文件指針將會放在文件的結尾。運行結果以上是讀取文件的方法。為了輸出中文,我們還需要指定一個參數為,另外規定文件輸出的編碼。
上一篇文章:Python3網絡爬蟲實戰---30、解析庫的使用:PyQuery
下一篇文章:Python3網絡爬蟲實戰---32、數據存儲:關系型數據庫存儲:MySQL
我們用解析器解析出數據之后,接下來的一步就是對數據進行存儲了,保存的形式可以多種多樣,最簡單的形式可以直接保存為文本文件,如 TXT、Json、CSV 等等,另外還可以保存到數據庫中,如關系型數據庫 MySQL,非關系型數據庫 MongoDB、Redis 等等。那么本章我們就來統一了解一下數據的保存方式。
文本存儲文件存儲形式可以是多種多樣的,比如可以保存成 TXT 純文本形式,也可以保存為 Json 格式、CSV 格式等,本節我們來了解下文本文件的存儲方式。
1、TXT文本存儲將數據保存到 TXT 文本的操作非常簡單,而且 TXT 文本幾乎兼容任何平臺,但是有個缺點就是不利于檢索,所以如果對檢索和數據結構要求不高,追求方便第一的話,可以采用 TXT 文本存儲,本節我們來看下利用 Python 保存 TXT 文本文件的方法。
1. 本節目標本節我們要保存知乎發現頁面的熱門問題部分,將其問題和答案統一保存成文本形式。
2. 基本實例首先可以用 Requests 將網頁源代碼獲取下來,然后使用 PyQuery 解析庫進行解析,接下來將提取的標題、回答者、回答保存到文本,代碼如下:
import requests from pyquery import PyQuery as pq url = "https://www.zhihu.com/explore" headers = { ??? "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36" } html = requests.get(url, headers=headers).text doc = pq(html) items = doc(".explore-tab .feed-item").items() for item in items: ??? question = item.find("h2").text() ??? author = item.find(".author-link-line").text() ??? answer = pq(item.find(".content").html()).text() ??? file = open("explore.txt", "a", encoding="utf-8") ??? file.write(" ".join([question, author, answer])) ??? file.write(" " + "=" * 50 + " ") ??? file.close()
在這里主要是為了演示文件保存的方式,因此 Requests 異常處理部分在此省去,我們首先用 Requests 提取了知乎發現頁面,然后將熱門問題的問題、回答者、答案全文提取出來,然后利用了Python提供的 open() 方法打開一個文本文件,獲取一個文件操作對象,這里賦值為 file,然后利用 file 對象的 write() 方法將提取的內容寫入文件,最后記得調用一下 close() 方法將其關閉,這樣抓取的內容即可成功寫入到文本中了。
運行程序,可以發現在本地生成了一個 explore.txt 文件.
這樣熱門問答的內容就被保存文文本形式了。
在這里 open() 方法的第一個參數即為要保存的目標文件名稱,第二個參數為 a,代表以追加方式寫入到文本,另外我們還指定了文件的編碼為utf-8,最后寫入完成之后,我們還需要調用 close() 方法來關閉文件對象。
在剛才的實例中,第二個參數我們設置成了 a,這樣在每次寫入文本時不會清空源文件,而是在文件末尾寫入新的內容,這是一種文件打開方式。關于文件打開方式,其實還有另外的幾種,在此列舉如下:
r,以只讀方式打開文件。文件的指針將會放在文件的開頭。這是默認模式。
rb,以二進制格式打開一個文件用于只讀。文件指針將會放在文件的開頭。這是默認模式。
r+,打開一個文件用于讀寫。文件指針將會放在文件的開頭。
rb+,以二進制格式打開一個文件用于讀寫。文件指針將會放在文件的開頭。
w,打開一個文件只用于寫入。如果該文件已存在則將其覆蓋。如果該文件不存在,創建新文件。
wb ,以二進制格式打開一個文件只用于寫入。如果該文件已存在則將其覆蓋。如果該文件不存在,創建新文件。
w+, 打開一個文件用于讀寫。如果該文件已存在則將其覆蓋。如果該文件不存在,創建新文件。
wb+,以二進制格式打開一個文件用于讀寫。如果該文件已存在則將其覆蓋。如果該文件不存在,創建新文件。
a,打開一個文件用于追加。如果該文件已存在,文件指針將會放在文件的結尾。也就是說,新的內容將會被寫入到已有內容之后。如果該文件不存在,創建新文件進行寫入。
ab 以二進制格式打開一個文件用于追加。如果該文件已存在,文件指針將會放在文件的結尾。也就是說,新的內容將會被寫入到已有內容之后。如果該文件不存在,創建新文件進行寫入。
a+,打開一個文件用于讀寫。如果該文件已存在,文件指針將會放在文件的結尾。文件打開時會是追加模式。如果該文件不存在,創建新文件用于讀寫。
ab+,以二進制格式打開一個文件用于追加。如果該文件已存在,文件指針將會放在文件的結尾。如果該文件不存在,創建新文件用于讀寫。
4. 簡化寫法另外文件寫入還有一種簡寫方法,那就是使用 with as 語法,在 with 控制塊結束時,文件會自動關閉,所以就不需要再調用 close() 方法了。
所以上面的保存方式我們可以簡寫如下:
with open("explore.txt", "a", encoding="utf-8") as file: ??? file.write(" ".join([question, author, answer])) ??? file.write(" " + "=" * 50 + " ")
如果想保存時將原文清空,那么可以將第二個參數改寫為 w,代碼如下:
with open("explore.txt", "w", encoding="utf-8") as file: ??? file.write(" ".join([question, author, answer])) ??? file.write(" " + "=" * 50 + " ")5. 結語
以上便是利用 Python 將結果保存為 TXT 文件的方法,此種方法簡單易用,操作高效,是一種最基本的保存數據的方法。
2、Json文件存儲Json,全稱為 JavaScript Object Notation, 也就是 JavaScript 對象標記,通過對象和數組的組合來表示數據,構造簡潔但是結構化程度非常高,它是一種輕量級的數據交換格式,本節我們來了解一下利用 Python 保存數據到 Json 文件的方法。
1. 對象和數組在 JavaScript 語言中,一切都是對象。因此,任何支持的類型都可以通過 Json 來表示,例如字符串、數字、對象、數組等。但是對象和數組是比較特殊且常用的兩種類型。
對象,對象在 JavaScript 中是使用花括號 {} 包裹起來的內容,數據結構為 {key1:value1, key2:value2, ...} 的鍵值對結構。在面向對象的語言中,key 為對象的屬性,value 為對應的值。鍵名可以使用整數和字符串來表示。值的類型可以是任意類型。數組,數組在 JavaScript 中是方括號 [] 包裹起來的內容,數據結構為 ["java", "javascript", "vb", ...] 的索引結構。在 JavaScript 中,數組是一種比較特殊的數據類型,它也可以像對象那樣使用鍵值對,但還是索引使用得多。同樣,值的類型可以是任意類型。所以一個 Json 對象可以寫為如下形式:
[{ ??? "name": "Bob", ??? "gender": "male", ??? "birthday": "1992-10-18" }, { ???? "name": "Selina", ??? "gender": "female", ??? "birthday": "1995-10-18" }]
由中括號包圍的就相當于列表類型,列表的每個元素可以是任意類型,在示例中它是字典類型,由大括號包圍。
Json 可以由以上兩種形式自由組合而成,可以無限次嵌套,結構清晰,是數據交換的極佳方式。
Python 為我們提供了簡單易用的 json 庫來供我們實現 Json 文件的讀寫操作,我們可以調用 json 庫的 loads() 方法將 Json 文本字符串轉為 Json 對象,可以通過 dumps()方法將 Json 對象轉為文本字符串。
例如在這里有一段 Json 形式的字符串,它是 str 類型,我們用 Python 將可其轉換為可操作的數據結構,如列表或字典。
import json str = """ [{ ??? "name": "Bob", ??? "gender": "male", ??? "birthday": "1992-10-18" }, { ??? "name": "Selina", ??? "gender": "female", ??? "birthday": "1995-10-18" }] """ print(type(str)) data = json.loads(str) print(data) print(type(data))
運行結果:
[{"name": "Bob", "gender": "male", "birthday": "1992-10-18"}, {"name": "Selina", "gender": "female", "birthday": "1995-10-18"}]
在這里我們使用了 loads() 方法將字符串轉為 Json 對象,由于最外層是中括號,所以最終的類型是列表類型。
這樣一來我們就可以用索引來取到對應的內容了,例如我們想取第一個元素里的 name 屬性,就可以使用如下方式獲?。?/p>
data[0]["name"] data[0].get("name")
得到的結果都是:
Bob
通過中括號加 0 索引我們可以拿到第一個字典元素,然后再調用其鍵名即可得到相應的鍵值。在獲取鍵值的時候有兩種方式,一種是中括號加鍵名,另一種是 get() 方法傳入鍵名。推薦使用 get() 方法來獲取內容,這樣如果鍵名不存在的話不會報錯,會返回None。另外 get() 方法還可以傳入第二個參數即默認值,我們用一個示例感受一下:
data[0].get("age") data[0].get("age", 25)
運行結果:
None 25
在這里我們嘗試獲取年齡 age,其實在原字典中是不存在該鍵名的,如果不存在,默認會返回 None,如果傳入第二個參數即默認值,那么在不存在的情況下則返回該默認值。
值得注意的是 Json 的數據需要用雙引號來包圍,不能使用單引號。例如若使用如下形式表示則會出現錯誤:
import json str = """ [{ ??? "name": "Bob", ??? "gender": "male", ??? "birthday": "1992-10-18" }] """ data = json.loads(str)
運行結果:
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 3 column 5 (char 8)
在這里會出現 Json 解析錯誤的提示,是因為在這里數據用了單括號來包圍,請千萬注意 Json 字符串的表示需要用雙引號,否則 loads() 方法會解析失敗。
如果我們是從 Json 文本中讀取內容,例如在這里有一個data.json 文本文件,其內容是剛才我們所定義的 Json 字符串。
我們可以先將文本文件內容讀出,然后再利用 loads() 方法轉化。
import json with open("data.json", "r") as file: ??? str = file.read() ??? data = json.loads(str) ??? print(data)
運行結果:
[{"name": "Bob", "gender": "male", "birthday": "1992-10-18"}, {"name": "Selina", "gender": "female", "birthday": "1995-10-18"}]
以上是讀取 Json 文件的方法。
3. 輸出Json另外我們還可以調用 dumps() 方法來將 Json 對象轉化為字符串。
例如我們將剛上例中的列表重新寫入到文本。
import json data = [{ ??? "name": "Bob", ??? "gender": "male", ??? "birthday": "1992-10-18" }] with open("data.json", "w") as file: ??? file.write(json.dumps(data))
利用 dumps() 方法我們可以將 Json 對象轉為字符串,然后再調用文件的 write() 方法即可寫入到文本,結果如圖 5-2 所示:
圖 5-2 寫入結果
另外如果我們想保存 Json 的格式,可以再加一個參數 indent,代表縮進字符個數。
with open("data.json", "w") as file: ??? file.write(json.dumps(data, indent=2))
寫入結果如圖 5-3 所示:
圖 5-3 寫入結果
這樣得到的內容會自動帶有縮進,格式會更加清晰。
另外如果 Json 中包含中文字符,例如我們將之前的 Json 的部分值改為中文,再用之前的方法寫入到文本。
import json data = [{ ??? "name": "王偉", ??? "gender": "男", ??? "birthday": "1992-10-18" }] with open("data.json", "w") as file: ??? file.write(json.dumps(data, indent=2))
寫入結果如圖 5-4 所示:
圖 5-4 寫入結果
可以看到中文字符都變成了 Unicode 字符,這并不是我們想要的結果。
為了輸出中文,我們還需要指定一個參數 ensure_ascii 為 False,另外規定文件輸出的編碼。
with open("data.json", "w", encoding="utf-8") as file: ??? file.write(json.dumps(data, indent=2, ensure_ascii=False))
寫入結果如圖 5-5 所示:
圖 5-5 寫入結果
這樣我們就可以輸出 Json 為中文了,所以如果字典中帶有中文的內容我們需要設置 ensure_ascii 參數為 False 才可正常寫入中文。
本節我們了解了用 Python 進行 Json 文件讀寫的方法,在后面做數據解析時經常會用到,建議熟練掌握。
3、CSV文件存儲CSV,全稱叫做 Comma-Separated Values,中文可以叫做逗號分隔值或字符分隔值,其文件以純文本形式存儲表格數據。該文件是一個字符序列,可以由任意數目的記錄組成,記錄間以某種換行符分隔,每條記錄由字段組成,字段間的分隔符是其它字符或字符串,最常見的是逗號或制表符,不過所有記錄都有完全相同的字段序列,相當于一個結構化表的純文本形式,它相比 Excel 文件更加簡介,XLS 文本是電子表格,它包含了文本、數值、公式和格式等內容,而 CSV 中不包含這些內容,就是特定字符分隔的純文本,結構簡單清晰,所以有時候我們用 CSV 來保存數據是比較方便的,本節我們來講解下 Python 讀取和寫入 CSV 文件的過程。
1. 寫入在這里我們先看一個最簡單的例子:
import csv with open("data.csv", "w") as csvfile: ??? writer = csv.writer(csvfile) ??? writer.writerow(["id", "name", "age"]) ??? writer.writerow(["10001", "Mike", 20]) ??? writer.writerow(["10002", "Bob", 22]) ??? writer.writerow(["10003", "Jordan", 21])
首先打開了一個 data.csv 文件,然后指定了打開的模式為 w,即寫入,獲得文件句柄,隨后調用 csv 庫的 writer() 方法初始化一個寫入對象,傳入該句柄,然后調用 writerow() 方法傳入每行的數據即可完成寫入。
運行結束后會生成一個名為 data.csv 的文件,數據就成功寫入了,直接文本形式打開的話內容如下:
id,name,age 10001,Mike,20 10002,Bob,22 10003,Jordan,21
可以看到寫入的文本默認是以逗號分隔的,調用一次 writerow() 方法即可寫入一行數據,我們用 Excel 打開的結果如圖 5-6 所示:
圖 5-6 打開結果
如果我們想修改列與列之間的分隔符可以傳入 delimiter 參數,代碼如下:
import csv with open("data.csv", "w") as csvfile: ??? writer = csv.writer(csvfile, delimiter=" ") ??? writer.writerow(["id", "name", "age"]) ??? writer.writerow(["10001", "Mike", 20]) ??? writer.writerow(["10002", "Bob", 22]) ??? writer.writerow(["10003", "Jordan", 21])
例如這里在初始化寫入對象的時候傳入 delimiter 為空格,這樣輸出的結果的每一列就是以空格分隔的了,內容如下:
id name age 10001 Mike 20 10002 Bob 22 10003 Jordan 21
另外我們也可以調用 writerows() 方法同時寫入多行,此時參數就需要為二維列表,例如:
import csv with open("data.csv", "w") as csvfile: ??? writer = csv.writer(csvfile) ??? writer.writerow(["id", "name", "age"]) ??? writer.writerows([["10001", "Mike", 20], ["10002", "Bob", 22], ["10003", "Jordan", 21]])
輸出效果是相同的,內容如下:
id,name,age 10001,Mike,20 10002,Bob,22 10003,Jordan,21
但是一般情況下爬蟲爬取的都是結構化數據,我們一般會用字典來表示,在 csv 庫中也提供了字典的寫入方式,實例如下:
import csv with open("data.csv", "w") as csvfile: ??? fieldnames = ["id", "name", "age"] ??? writer = csv.DictWriter(csvfile, fieldnames=fieldnames) ??? writer.writeheader() ??? writer.writerow({"id": "10001", "name": "Mike", "age": 20}) ??? writer.writerow({"id": "10002", "name": "Bob", "age": 22}) ??? writer.writerow({"id": "10003", "name": "Jordan", "age": 21})
在這里我們先定義了三個字段,用 fieldnames 表示,然后傳給 DictWriter 初始化一個字典寫入對象,然后可以先調用 writeheader() 方法先寫入頭信息,然后再調用 writerow() 方法傳入相應字典即可,最終寫入的結果是完全相同的,內容如下:
id,name,age 10001,Mike,20 10002,Bob,22 10003,Jordan,21
這樣我們就可以完成字典到 CSV 文件的寫入了。
另外如果我們想追加寫入的話可以修改文件的打開模式,如將 open() 函數的第二個參數改成 a 就可以變成追加寫入,代碼如下:
import csv with open("data.csv", "a") as csvfile: ??? fieldnames = ["id", "name", "age"] ??? writer = csv.DictWriter(csvfile, fieldnames=fieldnames) ??? writer.writerow({"id": "10004", "name": "Durant", "age": 22})
這樣在上面的基礎上再執行這段代碼,文件內容便會變成:
id,name,age 10001,Mike,20 10002,Bob,22 10003,Jordan,21 10004,Durant,22
可見數據被追加寫入到了文件中。
如果我們要寫入中文內容的話可能會遇到字符編碼的問題,此時我們需要給 open() 參數指定一個編碼格式,比如這里再寫入一行包含中文的數據,代碼需要改寫如下:
import csv with open("data.csv", "a", encoding="utf-8") as csvfile: ??? fieldnames = ["id", "name", "age"] ??? writer = csv.DictWriter(csvfile, fieldnames=fieldnames) ??? writer.writerow({"id": "10005", "name": "王偉", "age": 22})
在這里需要給 open() 函數指定編碼,否則可能會發生編碼錯誤。
以上便是 CSV 文件的寫入方法。
另外如果我們接觸過 Pandas 等庫的話,可以調用 DataFrame 對象的 to_csv() 方法也可以非常方便地將數據寫入到 CSV 文件中。
我們同樣可以使用 csv 庫來讀取 CSV 文件,例如我們現在將剛才寫入的文件內容讀取出來,代碼如下:
import csv with open("data.csv", "r", encoding="utf-8") as csvfile: ??? reader = csv.reader(csvfile) ??? for row in reader: ??????? print(row)
運行結果:
["id", "name", "age"] ["10001", "Mike", "20"] ["10002", "Bob", "22"] ["10003", "Jordan", "21"] ["10004", "Durant", "22"] ["10005", "王偉", "22"]
在這里我們構造的是 Reader 對象,通過遍歷輸出了每行的內容,每一行都是一個列表形式,注意在這里如果 CSV 文件中包含中文的話需要指定文件編碼。
另外如果我們接觸過 Pandas 的話,可以利用 read_csv() 方法將數據從 CSV 中讀取出來,例如:
import pandas? as pd df = pd.read_csv("data.csv") print(df)
運行結果:
????? id??? name? age 0? 10001??? Mike?? 20 1? 10002???? Bob?? 22 2? 10003? Jordan?? 21 3? 10004? Durant?? 22 4? 10005????? 王偉?? 22
在做數據分析的時候此種方法用的比較多,也是一種比較方便的讀取 CSV 文件的方法。
3. 結語本節我們了解了 CSV 文件的寫入和讀取方式,它也是一種常用的數據存儲方式,需要熟練掌握。
上一篇文章:Python3網絡爬蟲實戰---30、解析庫的使用:PyQuery
下一篇文章:Python3網絡爬蟲實戰---32、數據存儲:關系型數據庫存儲:MySQL
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/44081.html
摘要:關系型數據庫有多種,如等等。一致性與原子性是密切相關的。持久性持續性也稱永久性,指一個事務一旦提交,它對數據庫中數據的改變就應該是永久性的。如此一來,我們就可以實現主鍵不存在便插入數據,存在則更新數據的功能了。 上一篇文章:Python3網絡爬蟲實戰---31、數據存儲:文件存儲下一篇文章:Python3網絡爬蟲實戰---33、數據存儲:非關系型數據庫存儲:MongoDB 關系型數據...
摘要:的安裝是一個輕量級的關系型數據庫,以表的形式來存儲數據,本節我們來了解下它的安裝方式。相關鏈接官方網站下載地址中文教程下的安裝推薦使用安裝,執行命令即可。上一篇文章網絡爬蟲實戰解析庫的安裝下一篇文章網絡爬蟲實戰存儲庫的安裝 上一篇文章:Python3網絡爬蟲實戰---3、解析庫的安裝:LXML、BeautifulSoup、PyQuery、Tesserocr下一篇文章:Python3網絡...
摘要:時間永遠都過得那么快,一晃從年注冊,到現在已經過去了年那些被我藏在收藏夾吃灰的文章,已經太多了,是時候把他們整理一下了。那是因為收藏夾太亂,橡皮擦給設置私密了,不收拾不好看呀。 ...
摘要:相關鏈接官方文檔安裝推薦使用安裝,命令如下運行完畢之后即可完成的安裝。上一篇文章網絡爬蟲實戰數據庫的安裝下一篇文章網絡爬蟲實戰庫的安裝 上一篇文章:Python3網絡爬蟲實戰---4、數據庫的安裝:MySQL、MongoDB、Redis下一篇文章:Python3網絡爬蟲實戰---6、Web庫的安裝:Flask、Tornado 在前面一節我們介紹了幾個數據庫的安裝方式,但這僅僅是用來存...
摘要:父節點我們可以用方法來獲取某個節點的父節點,我們用一個實例來感受一下運行結果在這里我們首先用選取了為的節點,然后調用了方法,得到其父節點,類型依然是類型。 上一篇文章:Python3網絡爬蟲實戰---29、解析庫的使用:BeautifulSoup下一篇文章:Python3網絡爬蟲實戰---31、數據存儲:文件存儲 在上一節我們介紹了 BeautifulSoup 的使用,它是一個非常強...
閱讀 964·2023-04-26 02:56
閱讀 9437·2021-11-23 09:51
閱讀 1850·2021-09-26 10:14
閱讀 2980·2019-08-29 13:09
閱讀 2154·2019-08-26 13:29
閱讀 571·2019-08-26 12:02
閱讀 3562·2019-08-26 10:42
閱讀 3000·2019-08-23 18:18