###### tags: `Programming Language`
# NTU Python與高效工作術_Formal
## Reference
:::info

## [**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

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)
* #### 看到這畫面代表完成兩步驗證機制

#### 2. 接下來我們需要一組 Google 的通行碼
[**通行碼**](https://support.google.com/accounts/answer/185833)



```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



```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/),進入"個人頁面"**

* **點選發行權杖**
