1. 程式人生 > >Class 15 - 1 資料儲存——檔案儲存

Class 15 - 1 資料儲存——檔案儲存

儲存的形式可以多種多樣,最簡單的形式是 接儲存為文字檔案,如 TXT、JSON、CSV等。還可以儲存到資料庫中,如關係型資料庫 MySQL ,非關係型資料庫 MongoDB、Redis等。

一、TXT文字儲存 

  1. 基本例項:
    • 可以用 requests 將網頁原始碼獲取下來,然後使用 pyquery 解析庫解析,接下來將提取的標題、 回答者、 回答儲存到文字,程式碼:

      import requests
      from pyquery import PyQuery as pq
      url = 'https://www.zhihu.com/explore'
      headers 
      = { 'User-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 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() answers = pq(item.find('.content').html()).text() file = open('explore.txt', 'a', encoding='utf-8') file.write('\n'.join([question, author, answers])) file.write('\n'+'='*50+'\n') file.close()

      用 requests 提取知乎的"發現"頁面,然後將熱門話題的問題、回答者、答案全文提取出來,然後利用 Python 提供的open()方法開啟一個文字檔案,獲取一個檔案操作物件,這裡賦值為 file,接著利用 file 對 象的 write()方法將提取的內容寫入檔案,最後呼叫 ιlose()方法將其關閉,這

      樣抓取的內容即可成功 寫入文字中了。

  2. 開啟方式
    • open()方法的第二個引數設定成了 a,這樣在每次寫入文字時不會清空原始檔, 而是在檔案末尾寫入新的內容,這是一種檔案開啟方式。 

      • r:以只讀方式開啟檔案。 檔案的指標將會放在檔案的開頭。 這是預設模式。

      • rb:以二進位制只讀方式開啟一個檔案。 檔案指標將會放在檔案的開頭。
      • r+:以讀寫方式開啟一個檔案, 檔案指標將會放在檔案的開頭。 
      • rb+:以二進位制讀寫方式開啟一個檔案。 檔案指標將會放在檔案的開頭。
      • w:以寫入方式開啟一個檔案。 如果該檔案已存在,則將其覆蓋。 如果該檔案不存在,則建立新檔案。 
      • wb:以二進位制寫入方式開啟一個檔案。 如果該檔案已存在,則將其覆蓋。 如果該檔案不存 在, 則建立新檔案
      • w+:以讀寫方式開啟一個檔案。 如果該檔案已存在,則將其覆蓋。 如果該檔案不存在,則創 建新檔案
      • wb+:以二進位制讀寫格式開啟一個檔案。 如果該檔案已存在, 則將其覆蓋。 如果該檔案不存 在, 則建立新檔案。
      • a: 以追加方式開啟一個檔案。 如果該檔案已存在,檔案指標將會放在檔案結尾, 如果該檔案不存在, 則建立新檔案來寫入。
      • ab:以二進位制追加方式開啟一個檔案。 如果該檔案已存在,則檔案指標將會放在檔案結尾,如果該檔案不存在,則建立新檔案來寫入
      • a+:以讀寫方式開啟一個檔案。 如果該檔案已存在,檔案指標將會放在檔案的結尾。 檔案打 開時會是追加模式。 如果檔案不存在,則建立新檔案來讀寫。
      • ab+:以二進位制追加方式開啟一個檔案。 如果該檔案已存在,則檔案指標將會放在檔案結尾。 如果該檔案不存在,則建立新檔案用於讀寫
  3. 簡化寫法
    • 使用 with as 語法。在 with 控制塊結束時,檔案會自動關閉,不需要再呼叫 close()方法。示例:
        with open('explore.txt', 'a', encoding='utf-8') as file:
              file.write('\n'.jason([question,author,answers]))
              file.write('\n'+'='*50+'\n')

       如果想儲存時將原文清空,那麼可以將第二個引數改寫為 w,示例:

         with open('explore.txt', 'w', encoding='utf-8') as file:
              file.write('\n'.jason([question,author,answers]))
              file.write('\n'+'='*50+'\n')

二、Json檔案儲存

JSON,全稱為 JavaScript Object Notation, 是 JavaScript物件標記, 通過物件和陣列的組合來表示資料,構造簡潔但結構化程度非常高,是一種輕量級的資料交換格式。

  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": "Snlina",
               "gender": "female",
               "birthday": "1995-10-18"
          }]

          由中括號包圍的就相當於列表型別,列表中的每個元素可以是任意型別,這個示例中它是字典型別,由大括號包圍。
          JSON 可以由以上兩種形式自由組合而成,可以無限次巢狀,結構清晰,是資料交換的極佳方式。

  2. 讀取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))
      輸出:
      <class 'str'>
      [{'name': 'Bob', 'gender': 'male', 'birthday': '1992-10-18'}, {'name': 'Selina', 'gender': 'female', 'birthday': '1995-10-18'}]
      <class 'list'>
      View Code

      使用 loads()方法將字串轉為 JSON 物件。 由於最外層是中括號,所以最終的型別是列表型別

      針對列表,可以用索引來獲取對應的內容。 如,想取第一個元素裡的 name 屬性, 可以使用如下方式:

      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'
               },{
               'name': 'Selina',
              'gender':'female',
              'birthday':'1995-10-18'
      }]
      '''
      data = json.loads(str)
      輸出:
      json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 2 column 8 (char 8)
      View Code

      出現 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) 
  3. 輸出JSON

    • 可以呼叫 dumps()方法將 JSON 物件轉化為字串。 例:將例中的列表重新寫入文字:

      import json
      data = '''
          [{
          "name": "Bob",
          "gender": "male",
          "birthday": "1992-10-18"
      }]
      '''
      with open('data.json','a',encoding='utf-8') as f:
          f.write(json.dumps(data))

      利用 dumps()方法,可以將 JSON 物件轉為字串,然後再呼叫檔案的 write()方法寫入文字

    •  

      如果想儲存 JSON 的格式,可以再加一個引數 indent,代表縮排字元個數。 示例:

      with open('data.json','a',encoding='utf-8') as f:
          f.write(json.dumps(data,indent=2))

      這樣得到的內容會自動帶縮排,格式更加清晰。

    • 如果 JSON 中包含中文字元,需要指定引數 ensure_ascii 為 False,還要規定檔案輸出的編碼:

      with open('data.json','w',encoding='utf-8') as f:
          f.write(json.dumps(data,indent=2,ensure_ascii= False))

三、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()方法傳入每行的資料即可完成寫入。

      寫人的文字預設以逗號分隔,呼叫一次 writerow()方法即可寫入一行資料
    • 如果想修改列與列之間的分隔符,可以傳入 delimiter 引數,程式碼如下:

      import csv
      with open('data.csv','w') as csvfile:
          writer =csv.writer(csvfile,delimiter='')
          --snip--

      裡在初始化寫入物件時傳入 delimiter 為空格, 此時輸出結果的每一列就是以空格分隔

    • 也可以呼叫 writerows()方法同時寫入多行, 此時引數需要為二維列表,例:

      import csv
      with open('data.csv','w') as csvfile:
          writer =csv.writer(csvfile)
          writer.writerow(['id','name','age'])
          writer.writerow(['10001','Mike',20],['10002','Bob',22],['10003','Jordan',21])

      輸出內容相同。

    • 是一般情況下,爬蟲爬取的都是結構化資料,一般會用字典來表示。在 CSV 庫中也提供了字典的寫入方式,示例:

      import csv
      with open('data.csv','w') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          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})

      先定義 3 個欄位,用 fieldnames 表示,再將其傳給 DictWriter 來初始化一個字典寫人對 象,接著呼叫 writeheader()方法先寫人頭資訊,然後再呼叫 writerow()方法傳人相應字典。

    • 如果想追加寫人,可以修改檔案的開啟模式,即將 open()函式的第二個引數改成 a,示例:

      import csv
      with open('data.csv','a') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          writer.writerow({'id':'10004','name':'Durant','age':22})
    • 如果要寫入中文內容,可能會遇到字元編碼的問題,此時需要給 open()引數指定編碼格式。 例如,再寫入一行包含中文的資料,程式碼需要改寫:

      import csv
      with open('data.csv','a',encoding='utf-8') as csvfile:
          filenames = ['id','name','age']
          writer = csv.DictWriter(csvfile,fieldnames=filenames)
          writer.writerow({'id':'10005','name':'王偉','age':22})

      這裡需要給 open()函式指定編碼,否則可能發生編碼錯誤。

    • 如果接觸過 pandas 庫的話,可以呼叫 DataFrame 物件的 to_csv()方法來將資料寫人 csv 檔案中。

  2. 讀取

    • 同樣可以使用 csv 庫來讀取 csv 檔案。 如,將寫入的檔案內容讀取出來,如下:

      import csv
      with open('data.csv','r',encoding='utf-8') as csvfile:
          reader =csv.reader(csvfile)
          for row in reader:
              print(row)

      這裡構造的是 Reader 物件,通過遍歷輸出了每行的內容,每一行都是一個列表形式。 注意, 如果 csv 檔案中包含中文的話,還需要指定檔案編碼。

    • 如果知道 pandas庫,可以利用 read_csv()方法將資料從 csv 中讀取出來,如:

      import pandas as pd
      df=pd.read_csv('data.csv')
      print(df)

      在做資料分析的時候,此種方法用得比較多,也是一種比較方便地讀取 csv 檔案的方法。