網頁自動化

網頁自動化

大綱

hashlib 模組

Python 內建模組有 hashlib ,這個模組內有提供演算法將數據或稱資料轉成一個固定長度的 hash value 這個值稱為 哈希值 或 雜湊值 。常見產生哈希值的演算法有 : MD5、SHA1、SH224、SHA256、SHA384、SHA512...等。

  • MD5(Message-Digest Algorithm 5) : 我們可以稱是 訊息摘要演算法,這是一種廣泛被使用的密碼哈希 (hash) 函數,基本觀念是將一個數據轉換產生一個的哈希值 hash value ,未來可以由此哈希值驗證數據是否一致。在此,我們用大寫 MD5 ,實際應用此演算法是小寫 md5() 方法。
  • SHA1(Secure Hash Algorithm) : 中文稱 安全哈希演算法,這是 SHA 家族的一個演算法,常被應用在數位簽章,在此我們用大寫 SHA1,實際應用值演算法是小寫 sha1() 方法。

由於 hashlib 模組是 Python 內建的模組,所以使用前只要 import 此模組即可,如下所示 : 

import hashlib

使用 md5() 方法計算中文/英文資料的哈希值

模組內有 md5()、update()、digest()、hexdigest() 方法,可以將二進位的數據文件轉成哈希值。有個字串如下 :

name = ‘National Taiwan University’

如果想要轉換成二進位字串可以使用下列方式

name = b‘National Taiwan University’

在轉換數據文件成為哈希值時,必須使用 hashlib 模組的下列方法 :

  • md5() : 建立 md5() 方法的物件
  • update() : 更新數據文件內容
  • digest() : 將數據文件轉成哈希值
  • hexdigest() : 將數據文件轉成16進位的哈希值

範例 pythonHash-01.py : 使用 md5() 方法列出英文字串 ‘National Taiwan University’ 的哈希值,同時列出 md5() 物件與哈希值的資料型態。

# pythonHash-01.py
import hashlib

data = hashlib.md5()                                # 建立data物件
data.update(b'National Taiwan University')    # 更新data物件內容

print('Hash Value         = ', data.digest())
print('Hash Value(16進位) = ', data.hexdigest())
print(type(data))                                   # 列出data資料型態
print(type(data.hexdigest()))                       # 列出哈希值資料型態

執行結果

Hash Value         =  b'1\xc1zR\xe9H\xe3\xa9\xc8Y\xe0\xd9\x0b,\xc6r'
Hash Value(16進位) =  31c17a52e948e3a9c859e0d90b2cc672
<class '_hashlib.HASH'>
<class 'str'>

讀者可能會想,是否可以使用上述方法計算中文的哈希值呢? 答案是否定的。使用中文當作字串,會產生錯誤。這類狀況我們必須在 update() 方法內使用 encode(‘utf8’) 對中文字串進行編碼。

範例 pythonHash-02.py : 建立中文字串 ‘國立台灣大學’的哈希值 。

# pythonHash-02.py
import hashlib

data = hashlib.md5()                                # 建立data物件
school = '國立台灣大學'                             # 中文字串
data.update(school.encode('utf-8'))                 # 更新data物件內容

print('Hash Value         = ', data.digest())
print('Hash Value(16進位) = ', data.hexdigest())
print(type(data))                                   # 列出data資料型態
print(type(data.hexdigest()))                       # 列出哈希值資料型態

執行結果

Hash Value         =  b'\x114\xeb6\x9e\x97\xbfE\xf2=h\x1b\\\xdb\xbd\xe5'
Hash Value(16進位) =  1134eb369e97bf45f23d681b5cdbbde5
<class '_hashlib.HASH'>
<class 'str'>

計算檔案的哈希值

如果想要計算一個檔案的哈希值,可以使用二進位方式讀取檔案 (‘rb’) ,再將所讀取的二進位檔案內容放入 mc5() 方法中,然後計算哈希值。

範例 pythonHash-03.py : 在 Python 領域中最著名的學習格言是 Tim Peters 所寫的 Python 之禪( The Zen of Python),我們將此內容放在 dataHash.txt,此檔案內容如下,請計算此檔案的哈希值。

# pythonHash-03.py
import hashlib

data = hashlib.md5()                                # 建立data物件
filename = "dataHash.txt"

with open(filename, "rb") as fileName:                    # 以二進位方式讀取檔案
    binaryText = fileName.read()
    data.update(binaryText)

print('Hash Value         = ', data.digest())
print('Hash Value(16進位) = ', data.hexdigest())
print(type(data))                                   # 列出data資料型態
print(type(data.hexdigest()))                       # 列出哈希值資料型態

執行結果

Hash Value         =  b'h\xf1$*\xdf\xe4\xf4\xcb\x0e*\xac&K\xa5r\xd7'
Hash Value(16進位) =  68f1242adfe4f4cb0e2aac264ba572d7
<class '_hashlib.HASH'>
<class 'str'>

使用 sha1() 方法計算哈希值

計算哈希值時,如果想要使用 sha1() 方法很容易,只要將 md5() 方法改為 sha1() 方法即可。

範例 pythonHash-04.py : 使用 sha1() 方法重新設計範例 pythonHash-01.py

# pythonHash-04.py
import hashlib

data = hashlib.sha1()                               # 建立data物件
data.update(b'National Taiwan University')    # 更新data物件內容

print('Hash Value         = ', data.digest())
print('Hash Value(16進位) = ', data.hexdigest())
print(type(data))                                   # 列出data資料型態
print(type(data.hexdigest()))                       # 列出哈希值資料型態

執行結果

Hash Value         =  b'|\x02H\xd4\\\xee\xea\x195!\xce\xf7\xb8\xd7\xc6\xc5q\xaa\xae8'
Hash Value(16進位) =  7c0248d45ceeea193521cef7b8d7c6c571aaae38
<class '_hashlib.HASH'>
<class 'str'>

認識此平台可以使用的哈希演算法 

在 hashlib 模組內,可以使用 algorithms_available 屬性,這個屬性可以列出目前您所使用作業系統平台可以使用的哈希演算法。

範例 pythonHash-05.py : 列出你所使用的作業系統平台可以使用的哈希演算法。

# pythonHash-05.py
import hashlib

print(hashlib.algorithms_available)         # 列出此平台可使用的哈希演算法

執行結果

{'shake_128', 'shake_256', 'sha3_224', 'md5-sha1', 'sha3_384', 'mdc2', 'ripemd160', 'sha512', 'sha3_256', 'sha384', 'sha512_256', 'sha224', 'blake2s', 'whirlpool', 'sha1', 'md5', 'sha512_224', 'sha256', 'sha3_512', 'blake2b', 'md4', 'sm3'}

認識跨平台可以使用的哈希演算法

在 hashlib 模組內,可以使用 algorithms_quaranteed 屬性,這個屬性可以列出跨作業平台可以使用的哈希演算法。

範例 pythonHash-06.py : 列出跨作業系統平台可以使用的哈希演算法。

# pythonHash-06.py
import hashlib

print(hashlib.algorithms_guaranteed)         # 列出跨平台可使用的哈希演算法

執行結果

{'sha3_384', 'sha224', 'shake_128', 'sha1', 'sha3_512', 'sha256', 'blake2b', 'md5', 'sha384', 'shake_256', 'sha3_256', 'blake2s', 'sha512', 'sha3_224'}

環保署空氣品質JSON 檔案實作

下載與儲存 JSON 檔案

有關 JSON 資料的處理,請參考 :  JSON 數據資料Python 處理 JSON 數據資料。這裡我們將講解如何下載環保署空氣品質指標的 JSON 檔案,同時執行數據清洗、取得想要的內容。 首先到 空氣品質指標(AQI),可以選擇3種格式 JSON、CSV、XML 下載檔案。

另外選擇資料字典,可以看到每個欄位的說明。


範例 pythonHash-07.py : 讀取環保署空氣品質指標 AQI ,然後存入 aqi.json 檔案。

# pythonHash-07.py
import requests
import json

url = 'http://opendata.epa.gov.tw/webapi/Data/REWIQA/?$orderby=SiteName&$\
skip=0&$top=1000&format=json'
try:
    aqijsons = requests.get(url)                # 將檔案下載至aqijsons
    print('下載成功')
except Exception as err:
    print('下載失敗')
print(aqijsons.text)                            # 列印所下載的json檔案         
fn = "aqi.json"                                 # 建立欲儲存的json檔案 
with open(fn, 'w') as f:
    json.dump(aqijsons.json(),f)                # 寫入json檔案至aqi.json

JSON 檔案的數據清洗

之前我們從環保署下載了空氣品質指標 JSON 檔案,這個數據是複雜的,我們若只想留城市名稱、站台ID、PM2.5值、站台名稱,可以使用以下方式處理:

範例 pythonHash-08.py : 讀取環保署下載的空氣品質指標 aqi.json檔案,只列出城市名稱、站台ID、PM2.5值、站台名稱。

# pythonHash-08.py
import json

fileName = 'aqi.json'
with open(fileName, encoding='utf-8') as fileObj:
    getDatas = json.load(fileObj)                     # 讀json檔案

for getData in getDatas:
    county = getData['County']                      # 城市名稱
    sitename = getData['SiteName']                  # 站台名稱
    siteid = getData['SiteId']                      # 站台ID
    pm25 = getData['PM2.5']                         # PM2.5值    
    print('城市名稱 = %3s  站台ID = %3s  PM2.5值 = %2s  站台名稱 = %s ' %
          (county, siteid, pm25, sitename))

執行結果

城市名稱 = 基隆市  站台ID =   1  PM2.5值 =  8  站台名稱 = 基隆
城市名稱 = 新北市  站台ID =   2  PM2.5值 =  8  站台名稱 = 汐止
城市名稱 = 新北市  站台ID =   3  PM2.5值 = 11  站台名稱 = 萬里
城市名稱 = 新北市  站台ID =   4  PM2.5值 =  5  站台名稱 = 新店
城市名稱 = 新北市  站台ID =   5  PM2.5值 =  4  站台名稱 = 土城
......................

範例 pythonHash-09.py : 讀取環保署下載的空氣品質指標 aqi.json檔案,只列出台北市的站台ID、PM2.5值、站台名稱。

# pythonHash-09.py
import json

fn = 'aqi.json'
with open(fn,encoding='utf-8') as fnObj:
    getDatas = json.load(fnObj)                         # 讀json檔案

for getData in getDatas:
    if getData['County'] == '臺北市':
        sitename = getData['SiteName']                  # 站台名稱
        siteid = getData['SiteId']                      # 站台ID
        pm25 = getData['PM2.5']                         # PM2.5值    
        print('站台ID =%3s  PM2.5值 =%3s  站台名稱 = %s ' %
              (siteid, pm25, sitename))

執行結果

站台ID = 11  PM2.5值 =  6  站台名稱 = 士林
站台ID = 12  PM2.5值 =  6  站台名稱 = 中山
站台ID = 13  PM2.5值 =  4  站台名稱 = 萬華
站台ID = 14  PM2.5值 =  6  站台名稱 = 古亭
站台ID = 15  PM2.5值 =  9  站台名稱 = 松山
站台ID = 16  PM2.5值 = 21  站台名稱 = 大同
站台ID = 64  PM2.5值 =  3  站台名稱 = 陽明

紀錄環保署空氣品質 aqi.json 的哈希值

範例 pythonHash-10.py : 讀取環保署的空氣品質指標 aqi.json檔案,然後機算出此檔案的哈希值,並存入 outputPythonHash-01.txt 檔案中。

# pythonHash-10.py
import requests, hashlib, json

url = 'http://opendata.epa.gov.tw/webapi/Data/REWIQA/?$orderby=SiteName&$\
skip=0&$top=1000&format=json'
try:
    aqijsons = requests.get(url)                # 將檔案下載至htmlfile
    print('下載成功')
except Exception as err:
    print('下載失敗')

data = hashlib.md5()
data.update(aqijsons.text.encode('utf-8'))
hashdata = data.hexdigest()
print('環保署空氣品質指標 aqi.json 的哈希值 = ', hashdata)

fn = "outputPythonHash-01.txt"
with open(fn, 'w') as fileobj:
    fileobj.write(hashdata)

執行結果

下載成功
環保署空氣品質指標 aqi.json 的哈希值 =  bf3231d7fad0292d818aac7d6d669f00

檢測網站內容是否更新

範例 pythonHash-11.py : 檢測目前環保署的空氣品質指標 aqi.json檔案是否更新,判斷方式是使用哈希值,將這次讀取aqi.json檔案的哈希值跟上次的做比較,如果有更新,則儲存此JSON檔案為newAqi.json,並將哈希值存至 outputPythonHash-01.txt 檔案中。

# pythonHash-11.py
import requests, hashlib, json, os

def save_newaqi():
    '''儲存newaqi.json'''
    with open(fn, 'w') as f:
        json.dump(aqijsons.json(),f)            # 寫入json檔案至newaqi.json
def save_hashvalue():
    '''儲存哈希值至hashvalue.txt'''
    with open(fn_hash, 'w') as fileobj:
        fileobj.write(newhash)                  # 寫入哈希值至hashvalue.txt
def cal_hashvalue():
    ''' 計算hash value''' 
    data = hashlib.md5()
    data.update(aqijsons.text.encode('utf-8'))
    hashdata = data.hexdigest()
    return hashdata                             # 傳回哈希值

url = 'http://opendata.epa.gov.tw/webapi/Data/REWIQA/?$orderby=SiteName&$\
skip=0&$top=1000&format=json'
try:
    aqijsons = requests.get(url)                # 將檔案下載至aqijsons
    print('下載成功')
except Exception as err:
    print('下載失敗')

fn = 'newaqi.json'
fn_hash = 'hashvalue.txt'                       # 檔案名稱
if os.path.exists(fn_hash):                     # 如果hashvalue.txt存在
    newhash = cal_hashvalue()                   # 計算新的哈希值hashvalue
    print('newhash = ',newhash)
# 開啟hashvalue.txt檔案
    with open(fn_hash, 'r') as fnObj:           # 讀取舊的哈希值
        oldhash =  fnObj.read()
        print('oldhash = ', oldhash)        
    if newhash == oldhash:                      # 比對新舊哈希值
        print('環保署空氣品質資料未更新')
    else:
        print('環保署空氣品質資料已經更新')
        save_newaqi()                           # 儲存newaqi.son
        save_hashvalue()                        # 儲存哈希值至hashvalue.txt
else:                                           # 如果hashvalue.txt不存在
    print('第一次啟動此程式')
    newhvalue = cal_hashvalue()
    print('哈希值 = ', newhvalue)
    save_hashvalue()                            # 儲存哈希值至hashvalue.txt
    save_newaqi()

工作排程與自動執行

Window 10 有工作排程器,我們可以使用此功能自動執行所設計的程式,例如 : 我們想要使用 程式範例 pythonHash-11.py 監控空氣品質,可以使用下面流程 : 

首先,點選 開始 => Window 系統管理工具 => 工作排程器 :


出現工作排程式窗後 :

  • 點選 建立工作
  • 名稱 : 此工作的標題,這裡我們輸入 AQI AutoRun
  • 描述 : 此工作的詳細內容 
  • 點選 出發程序 => 新增

新增後,可以開始設定執行時間週期,然後按確定。

接著新增動作,點選 瀏覽,選擇要執行的程式,按確定。

按確定後,回到工作排程器的清單上,便可看到剛剛設定好的排程。

另外,我們可以在視窗右方,直接執行、結束、停用、刪除等功能。

環保署空氣品質的CSV 檔案

下載儲存 CSV 檔案

 空氣品質指標(AQI) 這裡,選擇 CSV 檔案,下載檔案。

數據清洗

範例 pythonHash-12.py : 讀取下載的空氣品質指標 aqi.csv 檔案,然後清洗數據,只留下城市名稱、站台ID、PM2.5值、站台名稱。

# pythonHash-12.py
import csv

infn = 'aqi.csv'                     # 來源檔案
outfn = 'outputPythonHash-02.csv'                               # 目的檔案
with open(infn,encoding='utf-8') as csvRFile:                        # 開啟csv檔案供讀取
    csvReader = csv.reader(csvRFile)                # 讀檔案建立Reader物件
    listReport = list(csvReader)                    # 將資料轉成串列 

newListReport = []                                  # 空串列
tmpList = []
for row in listReport:                              # 使用迴圈取新的欄位
    tmpList = [row[1],row[23],row[11],row[0]]
    newListReport.append(tmpList)

with open(outfn, 'w', newline = '',encoding='utf-8') as csvOFile:    # 開啟csv檔案供寫入
    csvWriter = csv.writer(csvOFile)                # 建立Writer物件   
    for row in newListReport:                       # 將串列寫入和列印
        csvWriter.writerow(row)                     # 寫入檔案
        if row[0] != 'County':                      # 不是標題
            print('城市名稱 =%4s  站台ID =%3s  PM2.5值 =%3s  站台名稱 = %s ' %
                  (row[0], row[1], row[2], row[3]))

執行結果

城市名稱 = 基隆市  站台ID =  1  PM2.5值 =  8  站台名稱 = 基隆
城市名稱 = 新北市  站台ID =  2  PM2.5值 =  8  站台名稱 = 汐止
城市名稱 = 新北市  站台ID =  3  PM2.5值 = 11  站台名稱 = 萬里
城市名稱 = 新北市  站台ID =  4  PM2.5值 =  5  站台名稱 = 新店
城市名稱 = 新北市  站台ID =  5  PM2.5值 =  4  站台名稱 = 土城
.........以下省略........

範例 pythonHash-13.py : 讀取下載的空氣品質指標 aqi.csv 檔案,然後清洗數據,只留下台北市的站台ID、PM2.5值、站台名稱。

# pythonHash-13.py
import csv

infn = 'outputPythonHash-02.csv'                    # 來源檔案
with open(infn,encoding='utf-8') as csvRFile:       # 開啟csv檔案供讀取
    csvReader = csv.reader(csvRFile)                # 讀檔案建立Reader物件
    listReport = list(csvReader)                    # 將資料轉成串列 

for row in listReport:                              # 使用迴圈取新的欄位
    if row[0] == '臺北市':                         
        print('站台ID =%3s  PM2.5值 =%3s  站台名稱 = %s ' %
              (row[1], row[2], row[3]))

執行結果

站台ID = 11  PM2.5值 =  6  站台名稱 = 士林
站台ID = 12  PM2.5值 =  6  站台名稱 = 中山
站台ID = 13  PM2.5值 =  4  站台名稱 = 萬華
站台ID = 14  PM2.5值 =  6  站台名稱 = 古亭
站台ID = 15  PM2.5值 =  9  站台名稱 = 松山
站台ID = 16  PM2.5值 = 21  站台名稱 = 大同
站台ID = 64  PM2.5值 =  3  站台名稱 = 陽明






參考資料

特色、摘要,Feature、Summary:

關鍵字、標籤,Keyword、Tag:

  • Web-Crawler,Data-Mining,Data-Science,Python,

留言

這個網誌中的熱門文章

Ubuntu 常用指令、分類與簡介

網路設定必要參數IP、netmask(遮罩)、Gateway(閘道)、DNS

iptables的觀念與使用

了解、分析登錄檔 - log

Python 與SQLite 資料庫

Blogger文章排版範本

Pandas 模組

如何撰寫Shell Script

查詢指令或設定 -Linux 線上手冊 - man

網路相關之指令