###### tags: `Programming Language` # NTU Python與高效工作術_Formal ## Reference :::info ![](https://i.imgur.com/aOVctOr.png) ## [**Link**](https://automatetheboringstuff.com/) ::: --- ## Environment Set Up * ### Windows #### [1. Install python 3.6.0](https://shaurong.blogspot.tw/2017/02/python-360-windows-2016.html) #### [2. Install VScode & Debug Settings](https://oranwind.org/python-vscode/) ## Note ### 1. 在 windows 底下、因爲編碼關係 ```python= # 路徑 '\' 符號需要在前面加上另一個 '\' print('c:\\spam\\eggs.png') # c:\spam\eggs.png # 或是要避免掉這個問題,可用 raw string (在字串前面加 'r') print(r'c:\spam\eggs.png') ``` ### 2. 針對有些人無法跑 pip 指令 ```python= py -m pip install 你的套件名稱 ``` ## Example * ### 1. R/W an Excel file *Install **openpyxl** package ifrst* **pip install openpyxl** * [**另一個強大的Excel套件 --- xlwings**](https://www.xlwings.org/) ```python= # Import Python excel library import openpyxl import os # The file directory os.chdir(r"D:\workspace\python") # workbook = openpyxl.load_workbook('stock_price_data.xlsx') # Get a sheet in a excel file sheet = workbook.get_sheet_by_name("2330") # i = 3; while True: if sheet.cell(row=i, column=2).value is None: break # Get the cell by row and column location result = (sheet.cell(row=i, column=2).value - float(sheet.cell(row=i-1, column=2).value)) / float(sheet.cell(row=i-1, column=2).value) print(result) sheet.cell(row=i, column=3).value = float(result) i=i+1 # Save the XLSX file workbook.save('stock_price_data.xlsx') ``` --- * ### 2-0. R/W a PDF file *Install **PyPDF2** package ifrst* **pip install PyPDF2** *Some kind of pdf would be unreadable* ```python= import PyPDF2 import os # Store the file path # 'r' means "Raw-String" os.chdir(r'D:\workspace\python\02_PDF_RW') # Open file with Read-Only attrubutes pdfFile = open('ror.pdf', 'rb') # pdfFile is a Python object. # Transfer pdfFile into PDF date format and can be read. reader = PyPDF2.PdfFileReader(pdfFile) # 可以把 writer 想象成是被寫入内容的暫存區. writer = PyPDF2.PdfFileWriter() # 取得 ror.pdf 檔案的第一頁. page1 = reader.getPage(0) # 注意 addPage 只能把一頁 pdf 放到新 pdf 檔的最後面 writer.addPage(page1) # 開啓一個名為 ror1.pdf 的新 pdf 檔案 outputPdf = open('ror1.pdf', 'wb') # 將目前 writer 物件的内容寫入新的 pdf 檔内 writer.write(outputPdf) # Close R/W file pointer outputPdf.close() pdfFile.close() # 取出該頁的文字. pageText = page1.extractText() print(pageText) ``` * ### 2-1. Muti-PDF file ```python= import PyPDF2 import os os.chdir(r'D:\workspace\python\02_PDF_RW') pdfFile = open('ror.pdf', 'rb') reader = PyPDF2.PdfFileReader(pdfFile) writer = PyPDF2.PdfFileWriter() for pageNum in range(reader.numPages): pdfPage = reader.getPage(pageNum) writer.addPage(pdfPage) for pageNum in range(reader.numPages): pdfPage = reader.getPage(pageNum) writer.addPage(pdfPage) outputPdf = open('ror_copy.pdf', 'wb') writer.write(outputPdf) pdfFile.close() outputPdf.close() ``` * ### 2-2. Watermark PDF file ```python= import PyPDF2 import os os.chdir(r'D:\workspace\python\02_PDF_RW') pdfFile = open('ror.pdf', 'rb') reader = PyPDF2.PdfFileReader(pdfFile) writer = PyPDF2.PdfFileWriter() watermarkReader = PyPDF2.PdfFileReader(open('watermark.pdf', 'rb')) # 取得 ror.pdf 第一頁 firstPage = reader.getPage(0) # 取得浮水印 watermark = watermarkReader.getPage(0) watermark.scale(0.5, 0.5) # 將浮水印以圖層的方式與 ror.pdf 第一頁結合 firstPage.mergePage(watermark) # 把結合后的結果存入 writer 暫存區 writer.addPage(firstPage) # 最後再將 writer 的内容寫入新的 pdf 檔 outputPdf = open('watermark_ror.pdf', 'wb') writer.write(outputPdf) pdfFile.close() outputPdf.close() ``` * ### 2-3. PDF to Word *UNnstall **docx** package ifrst* *Adn then install **python-docx** package ifrst* **uninstall docx** **pip install openpyxl** ```python= import PyPDF2 import os import docx os.chdir(r'D:\workspace\python\02_PDF_RW') pdfFile = open('ror.pdf', 'rb') # 將開啓的檔案進行解讀 reader = PyPDF2.PdfFileReader(pdfFile) # 取得這個 pdf 檔案一共有幾頁 totalPages = reader.numPages print(totalPages) # 38 # 創建一個新的 docx 檔案 document = docx.Document() for pageNum in range(reader.numPages): # 取出一頁 pdf 的内容 pageText = reader.getPage(pageNum).extractText() # 新增一個 word 段落,將一頁 pdf 的内容放入 document.add_paragraph(pageText) # 加上斷頁(下一個迭代換新頁) document.add_page_break() document.save('ror.docx') pdfFile.close() ``` --- * ### 3-0. Open an image file *Install **pillow** package ifrst* **pip install pillow** [下載Lenna 圖 ](https://www.dropbox.com/s/wso30w722raszj1/lenna_sharp.jpg?dl=1) ```python= # 引用 pillow 套件是 PIL, 而非 pillow, 取用 Image library from PIL import Image # 開啓影像檔 lenna = Image.open(r'D:\workspace\python\03_Image_Process\lenna_sharp.jpg') # 取得影像檔案大小 (以像素計算) width, height = lenna.size print(width, height) # (512, 512) # 取得圖檔格式 print(lenna.format) # JPEG ``` * ### 3-1. Image Scale ```python=0 from PIL import Image # 開啓原圖檔 lenna = Image.open(r'D:\workspace\python\03_Image_Process\lenna_sharp.jpg') # 取得影像檔案大小 (以像素計算) width, height = lenna.size print("{} {}".format(width, height)) # 輸入你想要的寬與高(以象素計算,記得放入整數) # 我們希望把圖縮小成原圖 1/2 的比例 # 最外層的左右括號是必要的 halfLenna = lenna.resize((int(width/2), int(height/2))) #最後別忘了將檔案存成一個圖檔 halfLenna.save(r'D:\workspace\python\03_Image_Process\lenna_sharp_halfScale.jpg') ``` * ### 3-2. Image rotation ```python=0 from PIL import Image # 開啓原圖檔 lenna = Image.open(r'D:\workspace\python\03_Image_Process\lenna_sharp.jpg') # 取得影像檔案大小 (以像素計算) width, height = lenna.size print("{} {}".format(width, height)) # 輸入你想要的寬與高(以象素計算,記得放入整數) # 我們希望把圖縮小成原圖 1/2 的比例 # 最外層的左右括號是必要的 halfLenna = lenna.resize((int(width/2), int(height/2))) # .rotate(n) 是指把圖檔以逆時鐘方向轉 n 度 halfLenna.rotate(180).save(r'D:\workspace\python\03_Image_Process\lenna_sharp_rotate.jpg') ``` * ### 3-3. Partial Cutting ![](https://i.imgur.com/tGjcAMT.png) 1. #### python 的 tuple ```python=0 # (a, b, c, d) 在 python 的世界是 tuple,一種資料結構 # 詳細的 xy 坐標可用小畫家查詢 box = (106, 51, 406, 512) ``` 2. #### tuple 在宣告時是用小括弧 \(\) 而非中括弧 \[\] ```python= pets_tuple = ('cat', 'dog', 'bird') # ('cat', 'dog', 'bird') ``` 3. #### 另外,tuple 是不可改變的,不支援新增,修改,刪除等功能 ```python= pets_tuple = ('cat', 'dog', 'bird') pets_tuple[0] = 'bat' # 會回傳錯誤! ``` ```python= from PIL import Image lenna = Image.open(r'D:\workspace\python\03_Image_Process\lenna_sharp.jpg') # 若想截取圖檔中的某一部分,可用 .crop 方法 # 需要指定一個四方形的範圍,(左上x, 左上y, 右下x, 右下y) # (a, b, c, d) 在 python 的世界是 set,一種資料結構 # 詳細的 xy 坐標可用小畫家查詢 box = (106, 51, 406, 512) cropLenna = lenna.crop(box) cropLenna.save(r'D:\workspace\python\03_Image_Process\lenna_sharp_cut.jpg') ``` * ### 4-0. Directory Checking *Install **shutil** package ifrst* shell utility 的縮寫,提供一些進階的檔案處理功能 **pip install shutil** 在Windows底下因為編碼的關係 ```python= # 路徑 '\' 符號需要在前面加上另一個 '\' print('c:\\spam\\eggs.png') # c:\spam\eggs.png # 或是要避免掉這個問題,可用 raw string (在字串前面加 'r') print(r'c:\spam\eggs.png') ``` * 單一檔案複製與資料夾複製的方式 ```python= import shutil import os # 複製檔案 shutil.copy(路徑1, 路徑2) # 複製整個資料夾,包含裏面的檔案和資料夾 shutil.copytree(資料夾路徑1, 資料夾路徑2) ``` * 程式範例 ```python= import os print('c:\\spam\\eggs.png') # c:\spam\eggs.png # or use raw string print(r'c:\spam\eggs.png') #----------------------------------------------- dir = r'D:\workspace\python\04_File_IO' # 會回傳你這個 python 程式碼檔案的路徑 print(os.getcwd()) # 會取得你在這個路徑下的所有路徑 listdir = os.listdir(dir) print(listdir) # 用回圈把每一個路徑都檢查一遍 for file in listdir: # 合并檔名和路徑 filepath = os.path.join(dir, file) print(filepath) # 檢查該路徑是否為檔案 if os.path.isfile(filepath): print("{} 是檔案".format(file)) # 檢查該路徑是否為資料夾 elif os.path.isdir(filepath): print("{} 是資料夾".format(file)) # 創造一個新的絕對路徑 backup_folder = os.path.join(dir, 'backup_folder') # 創造一個叫 backup_folder 的新資料夾在 dir 底下 os.makedirs(backup_folder) # 查詢該路徑占用的硬碟空間大小 print(os.path.getsize(dir)) ``` * ### 4.1 File & Tree copy ```python= import shutil import os # Distination path dist_path = r'D:\workspace\python\04_File_IO' # Source directory src_dir = r'D:\workspace\python\03_Image_Process' # Tree copy source src_tree_path = os.path.join(src_dir) # File distination Leanna_path = os.path.join(src_dir, 'lenna_sharp.jpg') print(Leanna_path) new_Leanna_dir = os.path.join(dist_path, 'new_Leanna_folder') tree_dist_dir = os.path.join(dist_path, 'backup_folder') # 會回傳你這個 python 程式碼檔案的路徑 os.chdir(src_dir) print(os.getcwd()) os.makedirs(new_Leanna_dir) # File copy shutil.copy(Leanna_path, new_Leanna_dir) # Tree copy shutil.copytree(src_tree_path, tree_dist_dir) print('Source path:'+ src_tree_path + ' ; Distination:' + tree_dist_dir ) ``` * ### 5-0. Send Email by gmail SMTP Install **SMTP** package ifrst **pip install smtplib** #### 1. 我們需要將Google的兩步驟驗證機制開啓 [**驗證連結**](https://myaccount.google.com/signinoptions/two-step-verification/enroll-welcome?pli=1) * #### 看到這畫面代表完成兩步驗證機制 ![](https://i.imgur.com/e5i3Cd0.png) #### 2. 接下來我們需要一組 Google 的通行碼 [**通行碼**](https://support.google.com/accounts/answer/185833) ![](https://i.imgur.com/KOtGaNQ.png) ![](https://i.imgur.com/YYPrcOr.png) ![](https://i.imgur.com/h363LpK.png) ```python= import smtplib ## 連上 gmail 服務 conn = smtplib.SMTP('smtp.gmail.com:587') # 開啓連綫 conn.ehlo() # 加密連綫 conn.starttls() # 申請 google 通行碼:https://support.google.com/accounts/answer/185833/ conn.login('Gmail address', 'Google 通行碼') # Email 需要 Subject(主題)、Msg内容、以及發送人姓名、用 \n\n (兩個分行) 來區分開來 conn.sendmail('送件人EMAIL', '收件人EMAIL', 'Subject: So long...\n\nSent from python!\n\n-test') # 別忘了退出連綫 conn.quit() ``` * ### 6-0. Facebook message *Install **Facebook chat** package ifrst **pip install fbchat** ```python= from fbchat import Client from fbchat.models import * thread_id = '你的聊天室ID' thread_type = ThreadType.GROUP # 個人討論串就改成 ThreadType.USER client = Client('FB mail', 'FB password') # 發送 Emoji client.sendEmoji(emoji='👍', size=EmojiSize.LARGE, thread_id=thread_id, thread_type=thread_type) # 發送文字訊息 client.send(Message(text='練習用Python送FB訊息,test! test! test!'), thread_id=thread_id, thread_type=thread_type) ``` * ### 7 Web Page Worm Install **HTTP protocol** package first Install **Beatuful soup** package first **pip intall requests** **pip intall bs4** [**參考 Yahoo 天氣 API**](https://developer.yahoo.com/weather/) * ### 7-0 Weather ```python= import requests result = requests.get("https://query.yahooapis.com/v1/public/yql?q=select%20item.forecast%2C%20item.condition%2C%20atmosphere%20%20%20from%20weather.forecast%20where%20woeid%20%3D%202306179%20and%20u%3D%22c%22%20limit%201&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys") print(result) # 別忘了左右括號 jsonData = result.json() print(jsonData) # 別忘了左右括號。將JSON不要的object拿掉 forecastData = jsonData['query']['results']['channel']['item']['forecast'] print(forecastData) # 最高與最低氣溫 highTemp = forecastData['high'] lowTemp = forecastData['low'] print('最高氣溫:{} 度,最低氣溫: {} 度'.format(highTemp, lowTemp)) ``` * ### 6-1 Send Weather Info. by email ```python= import smtplib from email.mime.text import MIMEText import requests result = requests.get("https://query.yahooapis.com/v1/public/yql?q=select%20item.forecast%2C%20item.condition%2C%20atmosphere%20%20%20from%20weather.forecast%20where%20woeid%20%3D%202306179%20and%20u%3D%22c%22%20limit%201&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys") jsonData = result.json() forecastData = jsonData['query']['results']['channel']['item']['forecast'] # 最高與最低氣溫 highTemp = forecastData['high'] lowTemp = forecastData['low'] sender = 'chen.jongoog@gmial.com' receiver = 'chen.jongoog@gmial.com' content = "你好: \n今日氣溫最高 {} 度,最低 {} 度 \n啾咪!".format(highTemp, lowTemp) msg = MIMEText(content.encode('utf-8'), _charset='utf-8') msg['Subject'] = '歡樂碼農天氣預報' msg['From'] = sender msg['To'] = receiver conn = smtplib.SMTP('smtp.gmail.com:587') conn.ehlo() conn.starttls() conn.login('你的EMAIL', '你的通行碼') conn.sendmail(sender, receiver, msg.as_string()) conn.quit() ``` * ### 7.2 Get the book price ![](https://i.imgur.com/xBbe5es.png) ![](https://i.imgur.com/ErL8INr.png) ![](https://i.imgur.com/NFPeT7p.png) ```python= import bs4 import requests res = requests.get('https://www.amazon.com/Zero-One-Notes-Startups-Future/dp/0804139296') #print(res.text) # 用 html 格式解碼 爬下來的檔案 soup = bs4.BeautifulSoup(res.text, 'html.parser') # Parse elements from Selector elems = soup.select('#buyNewSection > h5 > div > div.a-column.a-span8.a-text-right.a-span-last > div > span.a-size-medium.a-color-price.offer-price.a-text-normal') # 會回傳 [<span class="a-size-medium a-color-price offer-price a-text-normal">$xx.xx</span>] # 擷取 HTML Tag裡的 .text print(elems[0].text) ``` * ### 8. Line Message * **先上LINE官網[**登入**](https://notify-bot.line.me/zh_TW/),進入"個人頁面"** ![](https://i.imgur.com/5lKKBdK.png) * **點選發行權杖** ![](https://i.imgur.com/mJxhe70.png)