-
在 D 槽建立新資料夾 (python)
-
於 VS Code 的左上方工具列找到檔案 → 開啟資料夾 → 找到 D 槽建立的資料夾 (python)
-
新增檔案,主檔名 隨便 (建議英文),副檔名為 .py
-
切到終端機 (TERMINAL)
-
執行 → python 1_start.py →
enter
-
若要清空 TERMINAL 畫面 → cls
enter
-
註解:程式碼內打 #,# 後面可任意加寫文字,不會影響程式執行
-
字串:任意的文字內容
-
布林值:表達正確 (True) 或錯誤 (False),T&F需大寫
-
可變列表 (List):有順序、可變動的資料集合,ex. 學生的成績
-
固定列表 (Tuple):有順序、不可變動的資料集合
-
集合 (Set):無順序的資料集合,ex. 水果
-
字典:鍵值對 (Key-Value Pair) 的集合, 程式中做資料查詢 (ex. A對應到B)
- 變數用英文,開頭不可是數字
-
ex. 測試中文 是錯誤的語法,Python 語法為英文,但若想表達中文,用雙引號 (或單引號) 包起來,ex. "測試中文"、"HelloWorld"
-
雙引號 (或單引號) 中能寫任意文字
-
基本算術運算:加 (+)、減 (-)、乘 (*)、除 (/)、取餘數 (%)
-
除法詳解:整數除法 (//)、小數除法 (/)
-
X 的 Y 次方
X ** Y
、開根號X ** 0.5
-
表示法詳解:雙引號 (")、單引號 (')、多行文字
-
重複 & 串接:重複相同文字或串接多個字串
-
索引 & 字元:使用索引 [] 操作字串中的字元
-
x = x + 1
,左邊 x 為變數,右邊 (x + 1) 要先看 -
x = x + 1
可寫成x += 1
字串運算
s = "Hello"
print(s)
→
Hello
s = "Hell\"o"
print(s)
→
Hell"o
s = "Hello" + "World" = "Hello" "World"
print(s)
→
HelloWorld
s = "Hello\nWorld"
print(s)
→
Hello
World
s = """Hello
World"""
print(s)
→
Hello
World
s = "Hello" * 3
print(s)
→
HelloHelloHello
s = "Hello" * 3 + "World"
print(s)
→
HelloHelloHelloWorld
字串內部字元編號 (索引)
s = "Hello"
print(s[0])
→
H
s = "Hello"
print(s[2])
→
l
s = "Hello"
print(s[1: 4])
→
ell
-
List (List 的寫法為中括號 [] )
-
索引基本運用:取得、更新列表中的資料
-
連續資料處理:串接、取代、連續刪除列表中的資料
-
取得列表長度:len (列表)
-
巢狀列表:列表中的資料也是列表
-
-
Tuple ( Tuple 的寫法為小括號 () )
- 資料不可更動,操作與 List 相同,但資料不可更動
有序可變動列表List
grades = [12, 60, 15, 70, 90]
print(grades)
→
[12, 60, 15, 70, 90]
grades = [12, 60, 15, 70, 90]
print(grades[0])
→
12
grades = [12, 60, 15, 70, 90]
grades[0] = 55
print(grades)
→
[55, 60, 15, 70, 90]
grades = [12, 60, 15, 70, 90]
print(grades[1: 4])
→
[60, 15, 70]
grades = [12, 60, 15, 70, 90]
# 連續刪除列表
grades[1: 4] = []
print(grades)
→
[12, 90]
grades = [12, 60, 15, 70, 90]
grades = grades + [12, 33]
print(grades)
→
[12, 60, 15, 70, 90, 12, 33]
槽狀列表
data = [[3, 4, 5], [6, 7, 8]]
print(data[0][1])
→
4
data=[[3, 4, 5], [6, 7, 8]]
print(data[0][0: 2])
→
[3, 4]
data = [[3, 4, 5],[6, 7, 8]]
print(data)
data[0][0: 2] = [5, 5, 5]
print(data)
→
[[3, 4, 5], [6, 7, 8]]
[[5, 5, 5, 5], [6, 7, 8]]
Tuple 所有操作與 List 相同,但 Tuple 資料不可更動
data = (3, 4, 5)
data[0] = 5
print(data)
→
error
-
基本觀念:一群資料沒有順序性 (列表有順序概念,集合沒有)
-
判斷資料是否存在:使用 in 和 not in 運算符號
-
交集、聯集:使用 & 和 | 運算符號
-
交集:取兩個集合中相同的資料
-
聯集:取兩個集合中的所有資料,但不重複取
-
-
差集、反交集:使用 - 和 ^ 運算符號
-
差集:從A集合中減去和B集合重疊的資料
-
反交集:取兩個集合中不重疊的資料
-
-
-
字串拆解為集合:set (字串)
-
基本觀念:鍵值對 (Key-value Pair),一個索引對一個資料
-
key 對應 Value:字典[Key];字典[Key] = Value
-
判斷資料是否存在:使用 in 和 not in 運算符號
-
刪除鍵值對:使用 del 運算關鍵字
-
從列表建立字典:以列表的資料為基礎來建立字典
集合的運算
s1 = {3, 4, 5}
print(3 in s1)
→
True
s1 = {3, 4, 5}
print(10 in s1)
→
False
s1 = {3, 4, 5}
print(10 not in s1)
→
True
s1 = {3, 4, 5}
s2 = {4, 5, 6, 7}
s3 = s1 & s2
print(s3)
→
{4, 5}
s1 = {3, 4, 5}
s2 = {4, 5, 6, 7}
s3 = s1 | s2
print(s3)
→
{3, 4, 5, 6, 7}
s1 = {3, 4, 5}
s2 = {4, 5, 6, 7}
s3 = s1 - s2
print(s3)
→
{3}
s1 = {3, 4, 5}
s2 = {4, 5, 6, 7}
s3 = s1 ^ s2
print(s3)
→
{3, 6, 7}
s = set("Hello")
print(s)
→
{'H', 'o', 'e', 'l'}
s = set("Hello")
print("H" in s)
→
True
s = set("Hello")
print("h" in s)
→
False
字典的運算:Key-value 配對
dic = {"apple": "蘋果", "bug": "蟲蟲"}
print(dic["apple"])
→
蘋果
dic = {"apple": "蘋果", "bug": "蟲蟲"}
dic["apple"] = "小蘋果"
print(dic["apple"])
→
小蘋果
dic = {"apple": "蘋果", "bug": "蟲蟲"}
print("apple" in dic)
→
True
dic = {"apple": "蘋果", "bug": "蟲蟲"}
print(dic)
del dic["apple"]
print(dic)
→
{'apple': '蘋果', 'bug': '蟲蟲'}
{'bug': '蟲蟲'}
從列表的資料產生字典
dic = {x: x * 2 for x in [3, 4, 5]}
print(dic)
→
{3: 6, 4: 8, 5: 10}
基本語法一
if 布林值:
若布林值為 True,執行命令
基本語法二
if 布林值:
若布林值為 True,執行命令
else:
若布林值為 False,執行命令
基本語法三
if 布林值一:
若布林值一為 True,執行命令
elif 布林值二:
若布林值二為 True,執行命令
else:
若布林值一和二為 False,執行命令
程式範例
x = input("請輸入數字:") # 基本輸入為字串型態
x = int(x) # 轉換為整數型態
if x > 200:
print("大於 200")
elif x > 100:
print("大於 100,小於 200")
else:
print("小於 100")
判斷式
if True:
print("True 執行")
→
True 執行
if False:
Print("True 執行")
→
(會直接被忽略)
if True:
print("True 執行")
else:
print("False 執行")
→
True 執行
if False:
print("True 執行")
else:
print("False 執行")
→
False 執行
x = input("請輸入數字:")
x = int(x)
if x > 100:
print("大於 100")
else:
print("小於等於 100")
→
請輸入數字:(在 TERMINAL 隨意輸入數字,ex. 200)
大於 100
x = input("請輸入數字:")
x = int(x)
if x > 100:
print("大於 100")
else:
print("小於等於 100")
→
請輸入數字:(在 TERMINAL 隨意輸入數字,ex. 50)
小於等於 100
x = input("請輸入數字:")
x = int(x)
if x > 200:
print("大於 200")
elif x > 100:
print("大於 100,小於等於 200")
else:
print("小於等於 100")
→
請輸入數字:150
大於 100,小於等於 200
n1 = int(input("請輸入數字一:"))
n2 = int(input("請輸入數字二:"))
op = input("請輸入運算:+、-、*、/:")
if op == "+":
print(n1 + n2)
elif op == "-":
print(n1 - n2)
elif op == "*":
print(n1 * n2)
elif op == "/":
print(n1 / n2)
else:
print("不支援的運算")
→
請輸入數字一:(在 TERMINAL 隨意輸入數字) enter
↓
請輸入數字二:(在 TERMINAL 隨意輸入數字) enter
↓
請輸入運算:+、-、*、/:(在 TERMINAL 隨意輸入 +、-、*、/ 其一) enter
↓
(自動完成上述運算)
-
取得第一個數字放在 n1
-
取得第二個數字放在 n2
-
最後取得 +、-、*、/ 中的其中一個放在 op
-
判斷式進行判斷是否為 True,若為 True 則跑該段
基本語法
while 布林值:
若布林值為 True,執行命令
回到上方,做下一次的迴圈判斷
程式範例
n = 1
while n < 5:
print("變數 n 的資料是:", n)
n += 1
→
變數 n 的資料是: 1
變數 n 的資料是: 2
變數 n 的資料是: 3
變數 n 的資料是: 4
基本語法
for 變數名稱 in 列表或字串:
將列表中的項目或字串中的字元逐一取出,逐一處理
程式範例
n = 1
for x in [4, 1, 2]:
print("逐一取得列表中的資料", x)
→
逐一取得列表中的資料 4
逐一取得列表中的資料 1
逐一取得列表中的資料 2
for c in "Hello":
print("逐一取得字串中的字元", c)
→
逐一取得字串中的字元 H
逐一取得字串中的字元 e
逐一取得字串中的字元 l
逐一取得字串中的字元 l
逐一取得字串中的字元 o
使用 range()
for 變數名稱 in range(3)
相當於
for 變數名稱 in [0, 1, 2]
for 變數名稱 in range(3, 6)
相當於
for 變數名稱 in [3, 4, 5]
while 迴圈
n = 1
while True:
print(n)
n += 1
→
n = 1
while n <= 3:
print(n)
n += 1
→
1
2
3
1 加到 10 用 while 迴圈:
n = 1
sum = 0 # 紀錄累加的結果
while n <= 10:
sum = sum + n
n += 1
print(sum)
→
55
for 迴圈
for x in [3, 5, 1]:
print(x)
→
3
5
1
for x in "Hello":
print(x)
→
H
e
l
l
o
for x in range(5):
print(x)
→
0
1
2
3
4
for x in range(5, 10):
print(x)
→
5
6
7
8
9
1 加到 10 用 for 迴圈:
sum = 0
for x in range(1, 11): # 因為 0 不影響加法總和,所以 range(1, 11) 可寫成 range(11)
sum = sum + x
print(sum)
→
55
強制結束迴圈
while 布林值:
break
for 變數名稱 in 列表或字串:
break
程式範例
n = 1
while n < 5:
if n == 3:
break
n += 1
print(n)
→
3
程式邏輯:當 n = 1
,在 while n < 5:
中為 True,但在 if n == 3
為 False,所以不會執行 break
,n += 1
讓 n = 2
回到迴圈,當 n = 2
,在 while n < 5:
中為 True,但在 if n == 3
為 False 所以不會執行 break
,n + =1
讓 n = 3
回到迴圈,當 n = 3
,在 while n < 5:
中為 True,在 if n == 3
也為 True,執行 break
,停止程式
強制繼續下一圈
while 布林值:
continue
for 變數名稱 in 列表或字串:
continue
程式範例
n = 0
for x in [0, 1, 2, 3]:
if x % 2 == 0:
continue
n += 1
print(n)
→
2
程式邏輯:當 n = 0
,x = 0
進入 if x % 2 == 0
為 True,執行 continue 進入下一圈 (忽略下方 (n += 1) 程式碼),x = 1
進入 if x % 2 == 0
為 False,不會執行 continue,n += 1
讓 n = 1
,x = 2
進入 if x % 2 == 0
為 True,執行 continue 進入下一圈,x = 3
進入 if x % 2 == 0 為 False
,n += 1
讓 n = 2
基本語法
while 布林值:
若布林值為 True,執行命令
回到上方,做下一次的迴圈判斷
else:
迴圈結束前,執行此區塊的命令
for 變數名稱 in 列表或字串:
將列表中的項目或字串中的字元逐一取出,逐一處理
else:
迴圈結束前,執行此區塊的命令
程式範例
n = 1
while n < 5:
print("變數 n 的資料是:", n)
n += 1
else:
print(n)
→
5
for c in "Hello":
print("逐一取得字串中的字元", c)
else:
print(c)
→
o
break 的簡易範例
n = 0
while n < 5:
if n == 3:
break
print(n) # 印出迴圈中的 n
n += 1
print("最後的 n:", n) # 印出迴圈結束後的 n
→
0
1
2
最後的 n: 3
continue 的簡易範例
n = 0
for x in [0, 1, 2, 3]:
if x % 2 == 0: # x 是偶數 %:取餘數
continue
print(x)
n += 1
print("最後的 n:", n)
→
1
3
最後的 n: 2
else 的簡易範例
sum = 0
for n in range(11):
sum += n
else:
print(sum) # 印出 0 + 1 + 2 + 3 + ... + 10 的結果
→
55
綜合範例:找出整數平方根
n = input("輸入一個正整數:")
n = int(n) # 轉換輸入成數字
for i in range(n): # i 從 0 ~ n - 1
if i * i == n:
print("整數平方根", i)
break # 用 break 強制結束迴圈時,不會執行 else 區塊
else:
print("沒有整數的平方根")
→
輸入一個正整數:25 enter
整數平方根 5
n = input("輸入一個正整數:")
n = int(n) # 轉換輸入成數字
for i in range(n): # i 從 0 ~ n - 1
if i * i == n:
print("整數平方根", i)
break # 用 break 強制結束迴圈時,不會執行 else 區塊
else:
print("沒有整數的平方根")
→
輸入一個正整數:12 enter
沒有整數平方根
-
程式區塊 (函式:程式碼包裝在一個區塊中,方便隨時呼叫,函式就是一個程式區塊)
-
定義 > 呼叫:要先定義 (建立) 函式,然後才能呼叫 (使用) 函式
基本語法
def 函式名稱(參數名稱):
函式內部的程式碼
程式範例:定義一個印出 Hello 的函式
def sayHello():
print("Hello")
程式範例:定義可以印出任何訊息的函式
def say(msg):
print(msg)
程式範例:定義一個可以做加法的函式
def add(n1, n2):
result = n1 + n2
print(result)
基本語法
函式名稱(變數資料)
程式範例:定義一個印出 Hello 的函式
def sayHello():
print("Hello")
sayHello() # 呼叫上方定義的函式
程式範例:定義可以印出任何訊息的函式
def say(msg):
print(msg)
say("Hello Function") # 呼叫上方定義的函式
say("Hello Python") # 呼叫上方定義的函式
程式範例:定義一個可以做加法的函式
def add(n1, n2):
result = n1 + n2
print(result)
# 呼叫上方定義的函式
add(3, 4)
add(7, 8)
基本語法
def 函式名稱(參數名稱):
函式內部的程式碼
return # 結束函式,回傳None
程式範例:函式回傳 None
def say(msg):
print(msg)
return
# 呼叫函式,取得回傳值
value = say("Hello Function")
print(value)
→
None
程式範例:函式回傳字串 Hello
def add(n1, n2):
result = n1 + n2
return "Hello"
# 呼叫函式,取得回傳值
value = add(3, 4)
print(value)
→
Hello
程式邏輯:呼叫 add,3 放進 n1,4 放進 n2,3 + 4 = 7 放進 result,return 字串 Hello,字串 Hello 被丟回 add(3, 4)
,add(3, 4)
為字串 Hello = value,印出 value
函式內部的程式碼,若是沒有做函式呼叫,就不會執行
def multiply():
print(3 * 4)
→
無錯誤但不執行
def multiply():
print(3 * 4)
multiply()
→
12
def multiply():
print(3 * 4)
multiply()
multiply()
→
12
12
透過參數得到彈性
def multiply(n1, n2):
print(n1 * n2)
multiply(3, 4)
multiply(10, 8)
→
12
80
def multiply(n1, n2):
print(n1 * n2)
value=multiply(3, 4)
print(value)
→
12
None
def multiply(n1, n2):
print(n1 * n2)
return
value = multiply(3, 4)
print(value)
→
12
None
def multiply(n1, n2):
print(n1 * n2)
return 10
value = multiply(3, 4)
print(value)
→
12
10
def multiply(n1, n2):
print(n1 * n2)
return n1 * n2
value = multiply(3, 4)
print(value)
→
12
12
def multiply(n1, n2):
return n1 * n2
value = multiply(3, 4)
print(value)
→
12
def multiply(n1, n2):
print(n1 * n2)
return n1 * n2
value = multiply(3, 4)
→
12
回傳值的好處是可以在外部繼續操作
def multiply(n1, n2):
return n1 * n2
value = multiply(3, 4) + multiply(10, 5) # (3 * 4) + (10 * 5)
print(value)
→
62
同樣的邏輯可以重複利用
sum = 0
for n in range(1, 11):
sum = sum + n
print(sum)
sum = 0
for n in range(1, 21):
sum = sum + n
print(sum)
→
55
210
def calculate(max):
sum = 0
for n in range(1, max + 1):
sum = sum + n
print(sum)
calculate(10)
calculate(20)
→
55
210
基本語法
def 函式名稱(參數名稱 = 預設資料):
函式內部的程式碼
程式範例
# 參數 msg 預設資料為 "Hello"
def say(msg = "Hello"):
print(msg)
# 印出 Hello Function
say("Hello Function")
say() # 印出預設資料Hello
基本語法
def 函式名稱(名稱1, 名稱2):
函式內部的程式碼
# 呼叫函式,以參數名稱對應資料
函式名稱(名稱2 = 3, 名稱1 = 5)
程式範例
# 定義一個可以做除法的函數
def divide(n1, n2):
result = n1 / n2
print(result)
divide(2, 4) # 印出 0.5
divide(n2 = 2, n1 = 4) # 印出 2.0
基本語法
def 函式名稱(*無限參數):
無限參數以 Tuple 資料型態處理函式內部的程式碼
# 呼叫程式,可傳入無限數量的參數
函式名稱(資料一, 資料二, 資料三)
程式範例
# 函式接受無限參數 msgs
def say(*msgs):
# 以 Tuple 的方式處理
for msg in msgs
print(msg)
# 呼叫函式,傳入三個參數資料
say("Hello", "Arbitrary", "Arguments")
def power(base, exp = 0):
print(base ** exp)
power(3, 2)
power(4)
→
9
1
使用參數對應名稱
def divide(n1, n2):
print(n1 / n2)
divide(2, 4)
divide(n2 = 2, n1 = 4)
→
0.5
2.0
無限 / 不定 參數資料
def avg(*ns):
print(ns)
avg(3, 4)
avg(3, 5, 10)
avg(1, 4, -1, -8)
→
(3, 4)
(3, 5, 10)
(1, 4, -1, -8)
def avg(*ns):
for n in ns:
print(n)
avg(3, 4)
→
3
4
def avg(*ns):
sum = 0
for n in ns:
sum = sum + n
print(sum / len(ns))
avg(3, 4)
avg(3, 5, 10)
avg(1, 4, -1, -8)
→
3.5
6.0
-1.0
-
獨立的程式檔案:將程式寫在一個檔案中,此檔案可重複載入使用
-
載入 > 使用:先載入模組,再使用模組中的函式或變數
基本語法
import 模組名稱
import 模組名稱 as 模組別名
基本語法
模組名稱或別名.函式名稱(參數資料)
模組名稱或別名.變數名稱
程式範例
# 載入sys模組
import sys
# 使用 sys 模組
print(sys.platform) # 印出作業系統
print(sys.maxsize) # 印出整數型態的最大值
print(sys.path) # 印出搜尋模組的路徑
# 載入sys模組
import sys as s # s 是別名
# 使用 sys 模組
print(s.platform) # 印出作業系統
print(s.maxsize) # 印出整數型態的最大值
print(s.path) # 印出搜尋模組的路徑
- 載入與使用:載入 geometry 模組,並使用模組中定義的功能
import sys
print(sys.platform)
print(sys.maxsize)
→
win32
9223372036854775807
import sys as system
print(system.platform)
print(system.maxsize)
→
win32
9223372036854775807
- 先另開一個 Python 檔案命名 geometry.py,並在其中自訂模組
# 在 geometry 模組中定義幾何運算功能
# 計算兩個點的距離
def distance(x1, y1, x2, y2):
return ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
# 計算線段的斜率
def slope(x1, y1, x2, y2):
return (y2 - y1) / (x2 - x1)
import geometry
result=geometry.distance(1, 1, 5, 5)
print(result)
result=geometry.slope(1, 2, 5, 6)
print(result)
→
5.656854249492381
1.0
import sys
print(sys.path) # 印出模組的搜尋路徑列表
→
['D:\\Python-training','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\DLLs','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\lib','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310', 'C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages']
import sys
import geometry
print(geometry.distance(1, 1, 5, 5))
→
Traceback (most recent call last):
File "D:\Python-training\11_module.py", line 16, in <module>
import geometry
ModuleNotFoundError: No module named 'geometry'
import sys
sys.path.append("modules") # 在模組的搜尋路徑列表中[新增路徑]
print(sys.path) # 印出模組的搜尋路徑列表
print("========================================")
import geometry
print(geometry.distance(1, 1, 5, 5))
→
['D:\\Python-training','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\DLLs','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\lib','C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310', 'C:\\Users\\charmy\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages', 'modules']
========================================
5.656854249492381
-
檔案系統中的資料夾對應到 Python 的封包
-
檔案系統中的檔案對應到模組
專案檔案配置
- 專案資料夾
- 主程式.py
- 封包資料夾
- __init__.py
- 模組一.py
- 模組二.py
# 有裝 __init__.py 的資料夾才會被當作封包,若無 __init__.py 則為普通資料夾,__init__.py 裡面留空即可,但檔案要建立,__ 為兩個底線
專案檔案配置範例
- 專案資料夾
- main.py
- geometry
- __init__.py
- point.py
- line.py
基本語法
import 封包名稱.模組名稱
import 封包名稱.模組名稱 as 模組別名
-
新增資料夾 (backup),將先前程式移入其中
-
把程式放進 backup 後,要改寫成 python backup\檔案名.py 或先輸入 cd backup(資料夾名) 後輸入檔案名才能執行
-
新增封包並在其中建立檔案
__init__.py
、point.py
、line.py
def distance(x, y):
return (x ** 2 + y ** 2) ** 0.5
def len(x1, y1, x2, y2):
return ((x2 - x1) ** 2) + ((y2 - y1) ** 2) ** 0.5
def slope(x1, y1, x2, y2):
return (y2 - y1) / (x2 - x1)
import geometry.point
result = geometry.point.distance(3, 4)
print("距離", result)
import geometry.line
result = geometry.line.slope(1, 1, 3, 3)
print("斜率", result)
→
距離 5.0
斜率 1.0
import geometry.point as point
result = point.distance(3, 4)
print("距離", result)
import geometry.line as line
result = line.slope(1, 1, 3, 3)
print("斜率", result)
→
距離 5.0
斜率 1.0
基本語法
檔案物件 = open(檔案路徑, mode = 開啟模式)
-
開啟模式
-
讀取模式 - r
-
寫入模式(儲存) - w
-讀寫模式 – r+
讀取全部文字
檔案物件.read()
一次讀取一行
for 變數 in 檔案物件:
從檔案依序讀取每行文字到變數中
讀取 JSON 格式
import json
讀取到的資料 = json.load(檔案物件)
- 資料格式 JSON 使用的非常頻繁,經常用於網路中交換資料或儲存設定檔
寫入文字
檔案物件.write("字串")
寫入換行符號
檔案物件.write("這是範例文字\n")
寫入 JSON 格式
import json
json.dump(要寫入的資料, 檔案物件)
基本語法
檔案物件.close()
with open(檔案路徑, mode = 開啟模式) as 檔案物件:
讀取或寫入檔案的程式
# 以上區塊會自動、安全的關閉檔案
儲存檔案
file = open("data.txt", mode="w") # 開啟
file.write("Hello File") # 操作
file.close() # 關閉
→
產生新的檔案data.txt在資料夾裡
data.txt →
Hello File
file = open("data.txt", mode = "w")
file.write("Hello File\nSecond Line")
file.close()
→
data.txt →
Hello File
Second Line
file = open("data.txt", mode = "w")
file.write("測試中文\n好棒棒")
file.close()
→
data.txt →
���դ���
�n�δ�
# 出現亂碼
file = open("data.txt", mode = "w",encoding = "utf-8")
file.write("測試中文\n好棒棒")
file.close()
→
data.txt →
測試中文
好棒棒
with open("data.txt", mode = "w", encoding = "utf-8") as file:
file.write("測試中文\n好棒棒")
→
data.txt →
測試中文
好棒棒
讀取檔案 (讀取已經存在的檔案)
- 寫入:不存在沒關係,可以創造新檔案
with open("data.txt", mode = "r", encoding = "utf-8") as file:
data = file.read()
print(data)
→
測試中文
好棒棒
# 儲存檔案
with open("data.txt", mode = "w", encoding = "utf-8") as file:
file.write("5\n3")
# 讀取檔案
# 把檔案中的數字資料,一行一行的讀取出來,並計算總合
sum = 0
with open("data.txt", mode = "r", encoding = "utf-8") as file:
for line in file: # 一行一行讀取
sum += int(line)
print(sum)
→
8
使用 JSON 讀取格式、複寫檔案
{
"name":"My Name",
"version":"1,2,5"
}
import json
with open("config.json", mode = "r") as file:
data = json.load(file)
print(data) # 是一個字典資料
print("name:", data["name"])
print("version:", data["version"])
→
name: My Name
version: 1,2,5
修改資料
{
"name":"My Name",
"version":"1,2,5"
}
# 從檔案中讀取JSON資料,放入變數data裡面
with open("config.json", mode = "r") as file:
data = json.load(file)
print(data) # 是一個字典資料
data["name"] = "New Name" # 修改變數中的資料
# 把最新的資料複寫回檔案中
with open("config.json", mode = "w") as file:
json.dump(data,file)
→
{'name': 'New Name', 'version': '1,2,5'}
載入模組
import random
隨機選取
import random
# 從列表中隨機選取1個資料
random.choice([0, 1, 5, 8])
# 從列表中隨機選取2個資料
random.sample([0, 1, 5, 8], 2)
隨機調換順序
import random
# 將列表的資料「就地」隨機調換順序
data = [0, 1, 5, 8]
random.shuffle(data)
print(data)
隨機亂數
import random
# 取得 0.0 ~ 1.0 之間的隨機亂數
random.random()
random.uniform(0.0, 1.0)
常態分配亂數
import random
# 取得平均數 100、標準差 10 的常態分配亂數
random.normalvariate(100, 10)
載入模組
import statistics
使用模組
import statistics
# 計算列表中數字的平均數
statistics.mean([1, 4, 6, 9])
# 計算列表中數字的中位數
statistics.median([1, 4, 6, 9])
# 計算列表中數字的標準差
statistics.stdev([1, 4, 6, 9])
隨機選取:TERMINAL 每次出現的數字都不同
import random
data = random.choice([1, 5, 6, 10, 20])
print(data)
→
10
import random
data=random.sample([1, 5, 6, 10, 20], 3)
print(data)
→
[1, 20, 6]
隨機調換順序:隨機直接調換 data 本身順序,TERMINAL每次出現的順序都不同
import random
data=[1, 5, 8, 20]
random.shuffle(data)
print(data)
→
[8, 20, 1, 5]
隨機選取亂數:TERMINAL 每次出現的數字都不同
import random
data = random.random() # 0.0 ~ 1.0 之間的隨機亂數
print(data)
→
0.09932831340192749
import random
data = random.uniform(0.0, 1.0) # 0.0 ~ 1.0 之間的隨機亂數
print(data)
→
0.7038663863717032
import random
data = random.uniform(60, 100) # 60 ~ 100 之間的隨機亂數
print(data)
→
64.21584558160195
取得常態分配亂數
# 平均數100,標準差10,得到的資料多數在 90 ~ 110 之間
data = random.normalvariate(100, 10)
print(data)
→
112.49345426404079
# 平均數 0,標準差 5,得到的資料多數在 -5 ~ 5 之間
data = random.normalvariate(0, 5)
print(data)
→
7.198595824699282
import statistics as stat
data = stat.mean([1, 4, 5, 8])
print(data)
→
4.5
import statistics as stat
data = stat.mean([1, 2, 3, 4, 5, 8, 100])
print(data)
→
17.571428571428573
import statistics as stat
# 中位數不會被極端值影響
data = stat.median([1, 2, 3, 4, 5, 8, 100])
print(data)
→
4
import statistics as stat
data = stat.stdev([1, 2, 3, 4, 5, 8, 100])
print(data)
→
36.41820580816296
import statistics as stat
data = stat.stdev([1, 2, 3, 4, 5, 8, 10])
print(data)
→
3.251373336211726
載入模組
import urllib.request
下載特定網址資料
import urllib.request as request
with request.urlopen(網址) as response:
data=response.read()
print(data)
# request:別名(自己設定)
# response:物件
-
適合的資料來源
- ex. 台北市政府公開資料
-
確認資料格式
- ex. JSON、CSV 或其他格式
-
解讀 JSON 格式 → 使用內建的 json 模組
網路連線
import urllib.request as request
src = "http://www.ntu.edu.tw/"
with request.urlopen(src) as response:
data = response.read() # 取得台灣大學網站的原始碼 (HTML、CSS、JS)
print(data)
→
取得台灣大學網站的原始碼
import urllib.request as request
src = "http://www.ntu.edu.tw/"
with request.urlopen(src) as response:
data = response.read().decode("utf-8") # 取得台灣大學網站的原始碼 (HTML、CSS、JS)
print(data)
→
取得台灣大學網站的原始碼 (轉換中文)
-
google → data.taipei
-
搜尋:內湖科技
-
找到:台北市內湖科技園區廠商名錄
-
尋找 API 並複製網址
-
開啟新分頁貼上搜尋
-
此名錄為 JSON 格式
-
注意第一行 result 和 results (results 後面為陣列,即為 Python 的 list)
-
list (列表) 中有很多的字典 (JSON 的說法為有很多的物件)
- API:讓程式連線,自動下載
import urllib.request as request
import json
src = "https://data.taipei/api/v1/dataset/296acfa2-5d93-4706-ad58-e83cc951863c?scope=resourceAquire"
with request.urlopen(src) as response:
data = json.load(response) # 利用 json 模組處理 json 資料格式
print(data)
→
成功把台北市政府公開資料印在 console
將公司名稱列表出來
import urllib.request as request
import json
src = "https://data.taipei/api/v1/dataset/296acfa2-5d93-4706-ad58-e83cc951863c?scope=resourceAquire"
with request.urlopen(src) as response:
data=json.load(response) # 利用 json 模組處理 json 資料格式
# 將公司名稱列表出來
clist=data["result"]["results"]
print(clist)
→
資料格式最後只有一個列表 (一個中括號)
clist = data["result"]["results"],此寫法來自網頁中 JSON,data 為全部,result 和 results 為第一行的 result 和 results
import urllib.request as request
import json
src = "https://data.taipei/api/v1/dataset/296acfa2-5d93-4706-ad58-e83cc951863c?scope=resourceAquire"
with request.urlopen(src) as response:
data = json.load(response) # 利用 json 模組處理 json 資料格式
# 將公司名稱列表出來
clist=data["result"]["results"]
for company in clist:
print(company["公司名稱"])
→
公司名稱的乾淨列表
此資料中公司名稱為 key,對應的公司名稱為 value;統編為 key,統編號碼為 value
將公司名稱的乾淨列表抓到檔案中
import urllib.request as request
import json
src = "https://data.taipei/api/v1/dataset/296acfa2-5d93-4706-ad58-e83cc951863c?scope=resourceAquire"
with request.urlopen(src) as response:
data=json.load(response) # 利用json模組處理json資料格式
# 將公司名稱列表出來
clist = data["result"]["results"]
with open("data.txt", "w", encoding = "utf-8") as file:
for company in clist:
file.write(company["公司名稱"] + "\n")
→
產生新的檔案data.txt在資料夾裡
data.txt →
公司名稱的乾淨列表
-
封裝變數或函式:封裝的變數或函式,統稱類別的屬性
-
定義 > 使用:要先定義 (建立) 類別,然後才能使用類別中封裝的屬性
基本語法
class 類別名稱:
定義封裝的變數
定義封裝的函式
程式範例
# 定義Test類別
class Test:
x = 3 # 定義變數
def say() # 定義函式
print("Hello")
基本語法
類別名稱.屬性名稱
程式範例
# 定義 Test 類別
class Test:
x = 3 # 定義變數
def say() # 定義函式
print("Hello")
# 使用Test類別
Test.x+3 # 取得屬性x的資料3
Test.say() # 呼叫屬性say函式
# 定義類別,與類別屬性 (封裝在類別中的變數和函式)
# 定義一個類別 IO,有兩個屬性:supporttedSrcs 和 read
class IO:
supporttedSrcs=["console","file"]
def read(src):
print("Read from",src)
# 使用類別
print(IO.supporttedSrcs) # 印出列表
IO.read("file") # 呼叫類別中函式、屬性 # file 傳到 src → Read from file
→
['console', 'file']
Read from file
class IO:
supporttedSrcs=["console", "file"]
def read(src):
if src not in IO.supporttedSrcs:
print("Not Supported")
else:
print("Read from",src)
print(IO.supporttedSrcs)
IO.read("file")
IO.read("interent")
→
['console', 'file']
Read from file
Not Supported
-
定義類別
-
定義 supporttedSrcs 有的東西
-
定義讀取 src
-
若沒有在 supporttedSrcs
-
則印出 Not Supported
-
其餘則印出 Read from src (src 為讀取的內容)
-
印出 supporttedSrcs 內的東西
-
讀取 file (有在 supporttedSrcs 裡)
-
讀取 interest (沒有在 supporttedSrcs 裡)
注意如何定義類別,類別的屬性是什麼樣的概念,有了類別 (IO) 和類別的屬性 (supporttedSrcs、read) 後該如何使用 (IO.supporttedSrcs、IO.read),read 是一個函式,可以呼叫
-
類別與類別屬性
-
類別與實體物件、實體屬性
- 類別 → 建立實體物件 → 操作實體物件的屬性
-
透過類別建立:先定義類別,再透過類別建立實體物件
-
建立 > 使用:要先建立實體物件,然後才能使用實體屬性
基本語法
class 類別名稱:
# 定義初始化函式
def __init__(self):
# 透過操作 self 來定義實體屬性
# 建立實體物件,放入變數obj中
obj = 類別名稱() # 呼叫初始化函式
程式範例
class Point:
def __init__(self):
self.x = 3
self.y = 4
# 建立實體物件,此實體物件包含 x 和 y 兩個實體屬性
p = Point()
程式範例
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 建立實體物件,建立時,可直接傳入參數資料
p = Point(1, 5)
基本語法
實體物件.實體屬性名稱
程式範例
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 建立實體物件,並取得實體屬性資料
p = Point(1, 5)
print(p.x + p.y) # 1 + 5 = 6,印出 6
Point 實體物件的設計:平面座標上的點
class Point:
def __init__(self):
self.x = 3
self.y = 4
p1=Point() # 透過初始化函式,產生點的實體物件,放進變數裡
print(p1.x, p1.y)
→
3 4
建立第一個實體物件裝在 p1,再建立第二個實體物件裝在 p2,就是和類別 & 類別屬性操作不一樣的地方
class Point:
def __init__(self):
self.x = 3
self.y = 4
# 建立第一個實體物件
p1 = Point()
print(p1.x, p1.y)
# 建立第二個實體物件
p2 = Point()
print(p2.x, p2.y)
→
3 4
3 4
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
# 建立第一個實體物件
p1 = Point(3, 4)
print(p1.x, p1.y)
# 建立第二個實體物件
p2 = Point(5, 6)
print(p2.x, p2.y)
→
3 4
5 6
FullName 實體物件的設計:分開紀錄姓、名資料的全名
class FullName:
def __init__(self, first, last):
self.first=first
self.last=last
name1=FullName("Charmy", "Tseng")
print(name1.first, name1.last)
name2=FullName("G", "Bye")
print(name2.first, name2.last)
→
Charmy Tseng
G Bye
程式範例
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 建立實體物件,並取得實體屬性資料
p = Point(1, 5)
print(p.x + p.y)
基本語法
class類別名稱:
# 定義初始化函式
def __init__(self):
定義實體屬性
# 定義實體方法/函式 # 與初始化函式同一個階層
# 建立實體物件,放入變數obj中
obj = 類別名稱()
class類別名稱:
# 定義的初始化函式
def __init__(self):
#封裝在實體物件中的變數
def 方法名稱(self, 更多自訂參數):
# 方法主體,透過 self 操作實體物件
# 建立實體物件,放入變數 obj 中
obj = 類別名稱()
基本語法
實體物件.實體屬性名稱(參數資料) # 和函式呼叫動作相同
程式範例
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def show(self)
print(self.x, self.y)
p = Point(1, 5) # 建立實體物件
p = show() # 呼叫實體方法
-
Point:類別
-
x & y:實體屬性
-
show:實體方法
-
self:代表實體物件本身,一定要寫;
# 此段為初始化函式
def __init__(self, x, y):
self.x = x
self.y = y
Point 實體物件的設計:平面座標上的點
class Point:
def __init__(self,x,y):
self.x = x
self.y = y
# 定義實體方法
def show(self):
print(self.x, self.y)
p = Point(3, 4)
p.show() # 呼叫實體方法/函式
→
3 4
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
# 定義實體方法
def show(self):
print(self.x, self.y)
def distance(self, targetX, targetY):
return (((self.x - targetX) ** 2) + ((self.y - targetY) ** 2)) ** 0.5
p = Point(3, 4)
p.show() # 呼叫實體方法/函式
result = p.distance(0, 0) # 計算座標 3, 4 和座標 0, 0 之間的距離
print(result)
→
3 4
5.0
因為 distance 的這個函式是 return,把 (((self.x - targetX) ** 2) + ((self.y - targetY) ** 2)) ** 0.5
的結果利用 return 回傳,所以建立額外的變數 result 接收回傳的資料
def distance(self, targetX, targetY):
return(((self.x - targetX) ** 2) + ((self.y - targetY) ** 2)) ** 0.5
新增檔案
笨狗
好可愛
class file:
def __init__(self,name):
self.name = name
self.file = None # 尚未開啟檔案:初期是 None
def open(self):
self.file = open(self.name, mode = "r", encoding = "utf-8")
def read(self):
return self.file.read()
# 讀取第一個檔案
f1 = file("data1.txt")
f1.open()
data = f1.read()
print(data)
→
笨狗
class file:
# 初始化函式
def __init__(self, name):
self.name = name
self.file = None # 尚未開啟檔案:初期是 None
# 定義實體方法
def open(self):
self.file = open(self.name, mode = "r", encoding = "utf-8")
def read(self)
return self.file.read()
# 讀取第一個檔案
f1 = file("data1.txt")
f1.open()
data = f1.read()
print(data)
# 讀取第二個檔案
f2 = file("data2.txt")
f2.open()
data = f2.read()
print(data)
→
笨狗
好可愛
-
利用類別建立實體物件 (file)
-
建立初始化函式
-
建立兩個實體屬性 (name、file),file 初期是 None
-
定義實體方法
-
有兩個實體方法:open 方法 (調用 Python 內建的檔案開啟功能,得到一個檔案物件,放在實體屬性 file 裡面);read 方法 (利用剛剛得到的檔案物件做 read,把檔案讀取出來並且回傳)
-
這樣即完成一個定義 (一個實體物件的設計)
-
設計完後開始使用,使用方式
-
建立實體物件放在 f1,會呼叫初始化函式
-
利用變數 f1 代表實體物件呼叫實體方法 open
-
會開始跑
self.file = open(self.name, mode = "r", encoding = "utf-8")
-
呼叫另一個實體方法
-
就會開始跑
return self.file.read()
-
回傳資料放進 data 裡面
-
印出 data
-
定義 class 是為了產生實體物件,目標是包裝檔案讀取的程式
-
先有檔案名稱 檔案開啟 檔案讀取 將此流程包裝在實體物件中
-
none 為 Python 中特定的資料,代表空
-
檔案名稱由實體屬性中取得
-
f1 = file("data1.txt"):建立一個檔案的實體物件
-
有經過包裝的程式在做類似的程式會比較輕鬆
-
連線到特定網址,抓取資料
-
解析資料,取得實際想要的部分
- 關鍵心法:盡可能讓程式模仿一個普通使用者的樣子 (因為這些網站都不希望讓程式抓取資料)
-
JSON 格式資料:使用內建的 json 模組即可
-
HTML 格式資料 (網路上的網站大部分的格式)
-
- HTML 的格式以標籤為運作單位 (<>);</> 前方加斜線代表結束
<html>
<head>
<title>HTML 格式</title>
</head>
<body>
<div class="list">
<span>階層結構</span>
<span>樹狀結構</sapn>
</div>
</body>
</html>
安裝套件
-
pip 套件管理工具:安裝 Python 時,就一起安裝在電腦裡了
-
安裝 BeautifulSoup
pip install beautifulsoup4
抓取 PTT 電影版的網頁原始碼 (HTML)
-
抓取 PTT 電影版的網頁原始碼 (HTML)
-
連線到此網址 (要用程式連線上方網址)
-
(要抓到的是在網頁點右鍵:檢視網頁原始碼) ex:
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
with req.urlopen(url) as response:
data=response.read().decode("utf-8")
print(data)
→
出現一堆錯誤
(最後一行) urllib.error.HTTPError: HTTP Error 403: Forbidden
最後一行表示連線被拒絕,因為程式看起來不像正常使用者做連線 (一般網站皆不喜歡此種連線)
-
回到PTT電影版
-
在瀏覽器 (建議Chrome) 右上方的選單
-
更多工具
-
開發人員工具 (F12)
-
上方標籤選單選到 Network (網路監控的工具)
-
重新 PTT 電影版的網頁
-
尋找網頁本身 (通常在最上面 (index.html)) (記得左上角要選到All)
-
選擇Headers
-
(使用瀏覽器發送到PPT的伺服器會附加很多資訊,此附加資訊代表為正常使用者) 找Request Headers (裡面內容為一般使用者會發出的資訊)
-
找 user-agent (代表使用的作業系統、瀏覽器),此設定必須要有,將user-agent內容複製到程式中
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
print(data)
→
成功抓到網頁原始碼資料
解析原始碼,取得每天文章標題
# 抓取 PTT 電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request=req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser")
print(root.title)
→
<title>看板 movie 文章列表 - 批踢踢實業坊</title>
抓標籤裡的文字 (在 print(root.title) 後面加 string 即可)
# 抓取PTT電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser")
print(root.title.string)
→
看板 movie 文章列表 - 批踢踢實業坊
# 抓取PTT電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find("div", class_="title") # 尋找 class="title" 的 div 標籤
print(titles)
→
<div class="title">
<a href="/bbs/movie/M.1635954120.A.2E7.html">[新聞] 漫威老大太狠心 原本想要初代復仇者全滅</a>
</div
發現標籤裡有 a 標籤
# 抓取PTT電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request=req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data=response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root=bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles=root.find("div",class_="title") # 尋找 class="title" 的 div 標籤
print(titles.a.string)
→
[新聞] 漫威老大太狠心 原本想要初代復仇者全滅
抓到所有標題
# 抓取PTT電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data=response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles=root.find_all("div",class_="title") # 尋找所有 class="title" 的 div 標籤
print(titles)
→
[<div class="title">
<a href="/bbs/movie/M.1635954120.A.2E7.html">[新聞] 漫威老大太狠心 原本想要初代復仇者全滅</a>
</div>, <div class="title">
<a href="/bbs/movie/M.1635954704.A.D91.html">[新聞] 專訪/陳靜「永恆族」當裘莉粉絲 理察讚</a>
<a href="/bbs/movie/M.1635954725.A.F47.html">[請益] 怒火裡的個一疑問</a>
<a href="/bbs/movie/M.1635956755.A.DF8.html">[請益] 沒看漫威其他電影適合看永恆族嗎</a>
<a href="/bbs/movie/M.1635957112.A.9E0.html">[好微雷] 永恆族根本爆好看</a>
<a href="/bbs/movie/M.1635957256.A.653.html">[新聞] 克莉絲汀史都華雙喜曝婚訊! 打造黛妃</a>
<a href="/bbs/movie/M.1635959191.A.751.html">[ 好雷] 永恆族招誰惹誰</a>
<a href="/bbs/movie/M.1635959343.A.2E5.html">[贈票]【王者理查】威爾史密斯顛峰之作邀您見證</a>
<a href="/bbs/movie/M.1635960207.A.759.html">[好無雷] 永恆族 - 大師兄回來了 全都回來了 </a>
<a href="/bbs/movie/M.1635960741.A.4A9.html">[好無雷] 永恆族好看啊啊啊</a>
<a href="/bbs/movie/M.1635960996.A.EC4.html">[極好雷] 永恆族集結!Eternals Assemble!</a>
<a href="/bbs/movie/M.1635961086.A.C5A.html">[討論] 永恆族片兩個尾片段</a>
<a href="/bbs/movie/M.1635961311.A.579.html">[討論] 永恆族-漫威是不是政治正確玩上癮了</a>
<a href="/bbs/movie/M.1635961535.A.E3B.html">[好雷] 超乎預期的永恆族</a>
<a href="/bbs/movie/M.1630756788.A.1FE.html">[公告] 電影板板規 2021/9/4</a>
<a href="/bbs/movie/M.1630734048.A.152.html">[公告] 請注意防雷 / 分類</a>
<a href="/bbs/movie/M.1589355894.A.CDD.html">[情報] 近期院線預計重映片單</a>
<a href="/bbs/movie/M.1633428583.A.FAE.html">[情報] 2021 第58屆金馬獎 入圍名單</a>
<a href="/bbs/movie/M.1635917057.A.4A7.html">[情報] 2021 第58屆金馬獎 評審團</a>
</div>]
抓出資料 (用 for 迴圈)
# 抓取 PTT 電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
→
[新聞] 漫威老大太狠心 原本想要初代復仇者全滅
[新聞] 專訪/陳靜「永恆族」當裘莉粉絲 理察讚
[請益] 怒火裡的個一疑問
[請益] 沒看漫威其他電影適合看永恆族嗎
[好微雷] 永恆族根本爆好看
[新聞] 克莉絲汀史都華雙喜曝婚訊! 打造黛妃
[好雷] 永恆族招誰惹誰
[贈票]【王者理查】威爾史密斯顛峰之作邀您見證
[好無雷] 永恆族 - 大師兄回來了 全都回來了
[好無雷] 永恆族好看啊啊啊
[極好雷] 永恆族集結!Eternals Assemble!
[討論] 永恆族片兩個尾片段
[討論] 永恆族-漫威是不是政治正確玩上癮了
[好雷] 超乎預期的永恆族
[公告] 電影板板規 2021/9/4
[公告] 請注意防雷 / 分類
[情報] 近期院線預計重映片單
[情報] 2021 第58屆金馬獎 入圍名單
[情報] 2021 第58屆金馬獎 評審團
-
連線到特定網址,抓取資料
-
解析資料,取得實際想要的部分
- 關鍵心法:盡可能讓程式模仿一個普通使用者的樣子 (因為這些網站都不希望讓程式抓取資料)
-
Cookie:網站存放在瀏覽器的一小段內容
- 每個網站都可以在瀏覽器中存放一小段資料
-
與伺服器的互動:連線時,放在 Request Headers 中送出
HTML 超連結
<html>
<head>
<title>HTML 格式</title>
</head>
<body>
<a href= "http://www.google.com/">Google</a> <!-- 追蹤網頁的超連結抓到下一份網頁 -->
</body>
</html>
- ex. PPT 八卦版的第一頁,追蹤上一頁連結,抓第二頁,就可以持續追蹤上一頁抓很多的頁面
抓取 PTT 八卦版
-
Google 搜尋 PTT 八卦版並打開該網頁
-
要用程式連線上方網址
-
要抓到的是在網頁點右鍵:檢視網頁原始碼
# 抓取 PTT 電影版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/movie/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/Gossiping/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a !=None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
→
沒有抓到東西
-
回到 Google 搜尋 PTT 八卦版
-
在瀏覽器 (建議 Chrome) 右上方的選單
-
更多工具
-
開發人員工具 (F12)
-
上方標籤選單選到 Application
-
左邊選單選到 Cookies 後重新進入 PTT 八卦版
-
在 Cookies 找到 ptt.cc (PTT 的網站名稱)
-
會找到 5 個小資料 (Name:名字;Value:資料)
-
清除 Cookies (上方有 Clear all cookies)
-
重新整理網頁後 cookies 內沒有 over18 (需重新確認是否滿 18)
-
上方標籤選單選到 Network (網路監控的工具)
-
重新整理網頁
-
找 index.html
-
找 Request Headers (發出網路連線時帶出的附加資訊)
-
(Cookie 存放在瀏覽器,當瀏覽器和 PTT 連線時,會將 Cookie 放在 Request Headers 裡)在 Request Headers 中找到 cookie
-
cookie 中最重要的是 over18=1 (有用;隔開) (利用 over18=1 將存放在瀏覽器中的 cookie 送給伺服器,讓伺服器判斷是否再給一次確認畫面)
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/Gossiping/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
→
[問卦] 大家YT打開都是自家縣市長嗎?
[問卦] 老人真的有老人臭嗎
Re: [問卦] 基隆人不坐台鐵,鄉民不懂基隆的八卦??
Re: [新聞] 再見開羅!埃及宣布12月起「開始遷都」..
[問卦] 劉正風被滅門沒人要救?
Re: [新聞] 詐騙集團大哥枉死!酒店女套好招 母痛哭
Re: [問卦] 14天教召怎麼選人
[問卦] 為什麼南部人明顯比北部人好看?
[問卦] 花納稅人錢養網軍上網罵納稅人對嗎
[問卦] pixel真的有那麼神嗎
Re: [新聞] 快訊/迎戰「女版3Q」林靜儀 國民黨將派
Re: [問卦] 未繳欠費,真的有人被電信業者告過?
Re: [新聞] 北捷博愛座糾紛 69歲翁持剪刀刺人遭送辦
Re: [問卦] 基隆人不坐台鐵,鄉民不懂基隆的八卦??
Re: [新聞] 民進黨六都市長由蔡英文徵召 鄭文燦:我
[問卦] 香香豆的到底怎麼紅的?
[問卦] 護藻礁跟核四怎麼選
[新聞] 我精蟲減少!建築副理控:兒時遭調查局植入晶片...找徵信社
[問卦] 誰是台灣的平等院鳳凰
Re: [問卦] 最變態的港片
[公告] 八卦板板規(2021.05.11)
[協尋] 10月29日 觀音大同一路車禍
[公告] 十一月置底閒聊 國父誕辰的十一月
[公告] 魔王登基大典暨就職演說
-
在 PTT 八卦版中找到上頁的按鈕 (超連結,也就是
<a>
),所以,抓到第一個頁面之後,要動態的追縱上頁的超連結長什麼樣子,就在上頁上面點右鍵 -
檢查(就會找到超連結的樣子),並且發現在網頁中是
<a>
(a 的標籤),最特別的地方在於標籤內部的文字(‹ 上頁)
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/Gossiping/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data=response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取上一頁的連結
nextLink = root.find("a", string="‹ 上頁") # 找到內文是 ‹ 上頁 的 a 標籤
print(nextLink)
→
沒問題
(最後一行) <a class="btn wide" href="/bbs/Gossiping/index39194.html">‹ 上頁</a>
bs4 可根據條件找到想要的標籤:titles = root.find_all("div", class_="title")
中是根據 class;nextLink = root.find("a", string="‹ 上頁")
是根據內文 (標籤裡的內文) string
下個頁面的標籤在 nextLink,下個目標是屬性 (href),也就是
/bbs/Gossiping/index39194.html
,此時 nextLink 已代表<a>
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
url = "https://www.ptt.cc/bbs/Gossiping/index.html"
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data=response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title "的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取上一頁的連結
nextLink = root.find("a", string="‹ 上頁") # 找到內文是 ‹ 上頁 的 a 標籤
print(nextLink["href"])
→
沒問題
(最後一行)/bbs/Gossiping/index39195.html
整理程式碼 (用函式做包裝)
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
def getData(url):
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取上一頁的連結
nextLink = root.find("a", string="‹ 上頁") # 找到內文是 ‹ 上頁 的 a 標籤
print(nextLink["href"])
# 抓取一個頁面的標題
pageURL = "https://www.ptt.cc/bbs/Gossiping/index.html"
getData(pageURL)
→
沒問題
(最後一行)/bbs/Gossiping/index39195.html
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
def getData(url):
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data = response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取上一頁的連結
nextLink = root.find("a", string="‹ 上頁") # 找到內文是 ‹ 上頁 的 a 標籤
return nextLink["href"]
# 抓取一個頁面的標題
pageURL="https://www.ptt.cc/bbs/Gossiping/index.html"
pageURL="https://www.ptt.cc" + getData(pageURL)
print(pageURL)
→
沒問題
(最後一行) https://www.ptt.cc/bbs/Gossiping/index39197.html
-
呼叫函式 getData(pageURL)
-
網址 ("https://www.ptt.cc/bbs/Gossiping/index.html") 就會丟進去跑
-
跑完就會抓到上一頁的連結 (nextLink["href"])
-
之後就會 return 回到 getData(pageURL)
-
再覆蓋回 pageURL 裡面
getData(pageURL) 得到的是後面那一段 (/bbs/Gossiping/index.html) 所以前面手動加,"https://www.ptt.cc",形成 pageURL = "https://www.ptt.cc" + getData(pageURL)
# 抓取 PTT 八卦版的網頁原始碼 (HTML)
import urllib.request as req
def getData(url):
# 建立一個 Request 物件,附加 Request Headers 的資訊
request = req.Request(url, headers = {
"cookie":"over18=1",
"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36"
})
with req.urlopen(request) as response:
data=response.read().decode("utf-8")
# 解析原始碼,取得每天文章標題
import bs4
root = bs4.BeautifulSoup(data, "html.parser") # 讓 BeautifulSoup 協助解析 HTML 格式文件
titles = root.find_all("div", class_="title") # 尋找所有 class="title" 的 div 標籤
for title in titles:
if title.a != None: # 如標題包含 a 標籤 (沒有被刪除),印出來
print(title.a.string)
# 抓取上一頁的連結
nextLink = root.find("a", string="‹ 上頁") # 找到內文是 ‹ 上頁 的 a 標籤
return nextLink["href"]
# 主程式:抓取多個頁面的標題
pageURL = "https://www.ptt.cc/bbs/Gossiping/index.html"
count = 0
while count < 3: # 若想抓 3 頁就 < 3
pageURL = "https://www.ptt.cc" + getData(pageURL)
count += 1
→
成功
-
在程式中其實只加了
"cookie":"over18=1"
-
在 Request Heades 中加上 Cookie 的 Headers
-
把 over18=1 放進去 (代表連線曾經點過已滿 18 歲)
-
把本來的程式包裝在一個函式裡叫做 getData
-
然後傳遞網址進去
-
利用 url 去抓資料
-
研究原始碼,看看每個頁面的上一頁連結要怎麼抓 (要動態的抓到,因為每個頁面上一頁的網址都不一樣)
-
用 bs4 工具去尋找 a 標籤 (
nextLink=root.find("a",string="‹ 上頁")
) -
抓到 href 屬性,href = 一個網址 (網頁的超連結)
-
進行 return (丟回函式的外面)
-
包裝起來後外面的就是主程式
-
pageURL = "https://www.ptt.cc/bbs/Gossiping/index.html"
為第一頁 -
去抓下一頁後得到網址再去串上網站名稱
-
pageURL 就是上一頁的網址,再 +1 (
count+=1
)
-
連線到特定網址,抓取資料
-
解析資料,取得實際想要的部分
-
連線到特定網址,抓取資料
-
解析資料,取得實際想要的部分
-
安裝 Flask 套件
-
建立專案資料夾,撰寫程式
-
啟動伺服器,測試網站運作
Flask 套件
pip install Flask
-
建立網站專案:在電腦中的任意位置建立「專案資料夾」
-
撰寫程式:撰寫第一隻網站伺服器端的程式 (俗稱後端)
-
啟動網站:使用命令列執行 Python 程式,即啟動網站
-
測試網站:將網址貼到瀏覽器的網址列中,測試網站運作
-
在資料夾中創新資料夾 (flask-heroku)
-
VS Code 中點檔案
-
開啟資料夾
-
選 flask-heroku
-
在 TERMINAL 中輸 入pip install Flask
-
在專案中建立新的檔案 (app.py)
from flask import Flask
app = Flask(__name__) # __name__ 代表目前執行的模組
@app.route("/") # 函式的裝飾 (Decorator):以函式為基礎,提供附加的功能
def home():
return "Hello Flask"
if __name__ == "__main__": # 如果以主程式執行
app.run() # 立刻啟動伺服器
→
* Serving Flask app '23_app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
→
* Serving Flask app '23_app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Nov/2021 02:10:41] "GET / HTTP/1.1" 200 –
/:網站的根目錄;http://127.0.0.1:5000/ 為網址的主機
在網址上打 http://127.0.0.1:5000/test:因為 /test 網站沒有處理,網頁會告訴使用者找不到東西 (要不要處理可自己決定)
from flask import Flask
app = Flask(__name__) # __name__ 代表目前執行的模組
@app.route("/") # 函式的裝飾 (Decorator):以函式為基礎,提供附加的功能
def home():
return "Hello Flask 2"
@app.route("/test") # 代表我們要處理的網站路徑
def test():
return "This is Test"
if __name__ == "__main__": # 如果以主程式執行
app.run() # 立刻啟動伺服器
→
* Serving Flask app '23_app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
→
* Serving Flask app '23_app' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [06/Nov/2021 02:24:45] "GET / HTTP/1.1" 200 -
在網址後面加 /test(http://127.0.0.1:5000/test),即會顯示:This is Test
-
安裝 Flask 套件
-
安裝 Git
-
到 Heroku 註冊帳號、建立應用
-
安裝 Heroku 命令列工具
-
將程式部屬到 Heroku App,並測試
-
runtime.txt:描述使用的 Python 環境
-
requirements.txt:描述程式運作所需要的套件
-
Procfile:告訴 Heroku 如何執行程式
- Procfile:process file
- 安裝 Git 工具:搜尋 Git,下載並安裝 Git Tool
-
Heroku:註冊一個帳號
-
建立應用程式:選擇建立 Application 應用程式
- Heroku 命令列工具:按照 Heroku 官網,應用程式中的指示安裝
-
使用命令列模式:以下步驟使用命令列模式執行
-
登入 Heroku:heroku login
-
初始化專案:
-
git init
-
heroku git:remote -a 專案名稱 (一開始打就好)
-
-
更新專案:
-
git add .
-
git commit -m "更新的訊息"
-
git push heroku master(每次有更新就要打)
-
runtime.txt (告訴人家版本 )
python-3.10.0
requirements.txt (告訴人家專案在運作時需要哪些套件)
Flask
gunicorn
Procfile (告訴 Heroku 要怎麼啟動專案)
web gunicorn 24_app:app
- Google 搜尋 git → git 網站
- 點 Download for Winsows 下載 (windows 系統)
-
Google 搜尋 heroku 進入 Heroku 網站 (Heroku: Cloud Application Platform)
-
右上角 Sign Up
-
在 Heroku 網站中登入
-
按右上角的 New 後出現 Create new app 點進去
-
在 App name 中輸入名字 (python-training-setting),其餘不管
-
Create App → (進入畫面會顯示專案資訊)
-
點左上角 Personal
-
點剛剛建立的專案 (python-training-setting)
-
點上方的 Deploy (部署)
-
所謂的部署就是把寫的程式放到雲端,可以真正的在線上運作
-
下方也有教學
-
-
在網頁中看到 Install the Heroku CLI,點進去 (
ctrl + 滑鼠左鍵
會另開視窗) -
下方選擇安裝
→ git
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
<command> [<args>]
These are common Git commands used in various situations:
start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
init Create an empty Git repository or reinitialize an existing one
work on the current change (see also: git help everyday)
add Add file contents to the index
mv Move or rename a file, a directory, or a symlink
restore Restore working tree files
rm Remove files from the working tree and from the index
sparse-checkout Initialize and modify the sparse-checkout
examine the history and state (see also: git help revisions)
bisect Use binary search to find the commit that introduced a bug
diff Show changes between commits, commit and working tree, etc
grep Print lines matching a pattern
log Show commit logs
show Show various types of objects
status Show the working tree status
grow, mark and tweak your common history
branch List, create, or delete branches
commit Record changes to the repository
merge Join two or more development histories together
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
switch Switch branches
tag Create, list, delete or verify a tag object signed with GPG
collaborate (see also: git help workflows)
fetch Download objects and refs from another repository
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
→ heroku
CLI to interact with Heroku
VERSION
heroku/7.53.0 win32-x64 node-v12.21.0
USAGE
$ heroku [COMMAND]
COMMANDS
access manage user access to apps
addons tools and services for developing, extending, and operating your app
apps manage apps on Heroku
auth check 2fa status
authorizations OAuth authorizations
autocomplete display autocomplete installation instructions
buildpacks scripts used to compile apps
certs a topic for the ssl plugin
ci run an application test suite on Heroku
clients OAuth clients on the platform
config environment variables of apps
container Use containers to build and deploy Heroku apps
domains custom domains for apps
drains forward logs to syslog or HTTPS
features add/remove app features
git manage local git repository for app
help display help for heroku
keys add/remove account ssh keys
labs add/remove experimental features
local run Heroku app locally
logs display recent log output
maintenance enable/disable access to app
members manage organization members
notifications display notifications
orgs manage organizations
pg manage postgresql databases
pipelines manage pipelines
plugins list installed plugins
ps Client tools for Heroku Exec
psql open a psql shell to the database
redis manage heroku redis instances
regions list available regions for deployment
releases display the releases for an app
reviewapps manage reviewapps in pipelines
run run a one-off process inside a Heroku dyno
sessions OAuth sessions
spaces manage heroku private spaces
status status of the Heroku platform
teams manage teams
update update the Heroku CLI
webhooks list webhooks on an app
→ heroku login
heroku: Press any key to open up the browser to login or q to exit:
questor=SFMyNTY.g2gDbQAAAA0xMTEuMjUyLjQ1Ljg0bgYA-E68D30BYgABUYA.WtYRzcQM-uIM_a8COrYWRyLEhrIs9ZpL_G_qN3YNyM4
Logging in... done
Logged in as charmytseng0118@gmail.com
第 1 步
→ git init
Initialized empty Git repository in D:/Python-training/flask-heroku/python-training-setting/.git/
第 2 步
→ heroku git:remote -a python-training-setting
set git remote heroku to https://git.heroku.com/python-training-setting.git
第 1 步
→ git add .
第 2 步
→ git commit -am "make it better"
[master (root-commit) a72389b] make it better
4 files changed, 17 insertions(+)
create mode 100644 24_app.py
create mode 100644 Procfile
create mode 100644 requirements.txt
create mode 100644 runtime.txt
若是出現
Author identity unknown
*** Please tell me who you are.
Run
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
to set your account's default identity.
Omit --global to set the identity only in this repository.
fatal: unable to auto-detect email address (got 'charmy@DESKTOP-QH4EVI9.(none)')
則必須
→ git config --global user.name "Charmy"
→ git config --global user.email "charmytseng0118@gmail.com"
→ git commit -m "make it better"
[master (root-commit) 8e8c17a] make it better
5 files changed, 30 insertions(+)
create mode 100644 24_app.py
create mode 100644 Procfile
create mode 100644 requirements.txt
create mode 100644 runtime.txt
第 3 步
→ git push heroku master
Enumerating objects: 6, done.
Counting objects: 100% (6/6), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (6/6), 711 bytes | 711.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Determining which buildpack to use for this app
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote: -----> Installing python-3.10.0
remote: -----> Installing pip 21.3.1, setuptools 57.5.0 and wheel 0.37.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: Collecting Flask
remote: Downloading Flask-2.0.2-py3-none-any.whl (95 kB)
remote: Collecting gunicorn
remote: Downloading gunicorn-20.1.0-py3-none-any.whl (79 kB)
remote: Collecting itsdangerous>=2.0
remote: Downloading itsdangerous-2.0.1-py3-none-any.whl (18 kB)
remote: Collecting click>=7.1.2
remote: Downloading click-8.0.3-py3-none-any.whl (97 kB)
remote: Collecting Werkzeug>=2.0
remote: Downloading Werkzeug-2.0.2-py3-none-any.whl (288 kB)
remote: Collecting Jinja2>=3.0
remote: Downloading Jinja2-3.0.3-py3-none-any.whl (133 kB)
remote: Collecting MarkupSafe>=2.0
remote: Downloading MarkupSafe-2.0.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl (30 kB)nux_2_12_x86_64.manylinux2010_x86_64.whl (30 kB) rn, Flask
remote: Installing collected packages: MarkupSafe, Werkzeug, Jinja2, itsdangerous, click, gunico0.3 gunicorn-20.1.0 itsdangerous-2.0.1rn, Flask
remote: Successfully installed Flask-2.0.2 Jinja2-3.0.3 MarkupSafe-2.0.1 Werkzeug-2.0.2 click-8.0.3 gunicorn-20.1.0 itsdangerous-2.0.1
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 59.6M
remote: -----> Launching...
remote: Released v3
remote: https://python-training-setting.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/python-training-setting.git
* [new branch] master -> master
注意 https://stackoverflow.com/questions/65404309/heroku-error-during-git-push-deployment-the-same-version-of-this-code-has-alr
https://python-training- setting.herokuapp.com/ 為網站的正式網址,可以分享的真正在線上運作的網站
修改程式後
from flask import Flask
app = Flask(__name__) # __name__ 代表目前執行的模組
@app.route("/") # 函式的裝飾 (Decorator):以函式為基礎,提供附加的功能
def home():
return "Hello Flask 2"
@app.route("/test") # 代表我們要處理的網站路徑
def test():
return "This is Test 2"
if __name__ == "__main__": # 如果以主程式執行
app.run() # 立刻啟動伺服器
第 1 步
→ git add .
第 2 步
→ git commit -am "make it better"
[master c26f6f5] make it better
1 file changed, 1 insertion(+), 1 deletion(-)
第 3 步
→ git push heroku master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 382 bytes | 382.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote: Compressing source files... done.
remote: Building source:
remote:
remote: -----> Building on the Heroku-20 stack
remote: -----> Using buildpack: heroku/python
remote: -----> Python app detected
remote: -----> Using Python version specified in runtime.txt
remote: -----> No change in requirements detected, installing from cache
remote: -----> Using cached install of python-3.10.0
remote: -----> Installing pip 21.3.1, setuptools 57.5.0 and wheel 0.37.0
remote: -----> Installing SQLite3
remote: -----> Installing requirements with pip
remote: -----> Discovering process types
remote: Procfile declares types -> web
remote:
remote: -----> Compressing...
remote: Done: 59.5M
remote: -----> Launching...
remote: Released v4
remote: https://python-training-setting.herokuapp.com/ deployed to Heroku
remote:
remote: Verifying deploy... done.
To https://git.heroku.com/python-training-setting.git
a72389b..c26f6f5 master -> master
-
Pandas:概念類似試算表的資料分析套件
- Excel、Google Sheet
-
基礎學習項目:
-
安裝 Pandas 套件
-
認識單維度的資料 Series
-
認識雙維度的資料 DataFrame
-
安裝 Pandas
pip install pandas
建立 Series
# 載入 Pandas 模組
import pandas as pd # pd 是自己取的名字
# 以列表資料為底,建立 Series
pd.Series(列表)
- 使用 Series
import pandas as pd
data = pd.Series(列表)
data.max() # 找到最大值
data.median() # 找到中位數
data = data*2 # 放大兩倍
建立 DataFrame
# 載入 Pandas 模組
import pandas as pd
# 以字典資料為底,建立 DataFrame
pd.DataFrame(字典)
- 取得特定欄 (直向)
import pandas as pd
data = pd.DataFrame(字典)
data["欄位名稱"]
- 取得特定列 (橫向)
import pandas as pd
data = pd.DataFrame(字典)
data.iloc[列編號] # 列編號按順序由 0 開始累加
# 載入 pandas 模組
import pandas as pd
# 建立 Series
data = pd.Series([20, 10, 15])
# 基本 Series 操作
print(data)
→
0 20
1 10
2 15
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 建立 Series
data = pd.Series([20, 10, 15])
# 基本 Series 操作
print("Max", data.max())
print("Median", data.median())
data = data * 2
print(data)
→
Max 20
Median 15.0
0 40
1 20
2 30
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 建立 Series
data = pd.Series([20, 10, 15])
# 基本 Series 操作
data = data == 20
print(data)
→
0 True
1 False
2 False
dtype: bool
# 載入 pandas 模組
import pandas as pd
# 建立 DataFrame
data = pd.DataFrame({
"name": ["Amy", "John", "Bob"],
"salary": [80000, 60000, 55000]
})
# 基本 DataFrame 操作
print(data)
→
name salary
0 Amy 80000
1 John 60000
2 Bob 55000
取得特定的欄位
# 載入 pandas 模組
import pandas as pd
# 建立 DataFrame
data = pd.DataFrame({
"name": ["Amy", "John", "Bob"],
"salary": [80000, 60000, 55000]
})
# 取得特定的欄位
print(data["name"])
→
0 Amy
1 John
2 Bob
Name: name, dtype: object
# 載入 pandas 模組
import pandas as pd
# 建立 DataFrame
data = pd.DataFrame({
"name": ["Amy", "John", "Bob"],
"salary": [80000, 60000, 55000]
})
# 取得特定的欄位
print(data["salary"])
→
0 80000
1 60000
2 55000
Name: salary, dtype: int64
取得特定的列
# 載入 pandas 模組
import pandas as pd
# 建立 DataFrame
data = pd.DataFrame({
"name": ["Amy", "John", "Bob"],
"salary": [80000, 60000, 55000]
})
# 取得特定的列
print(data)
print("==============")
print(data.iloc[0]) # 印出第一列
→
name salary
0 Amy 80000
1 John 60000
2 Bob 55000
==============
name Amy
salary 80000
Name: 0, dtype: object
# 載入 pandas 模組
import pandas as pd
# 建立 DataFrame
data = pd.DataFrame({
"name": ["Amy", "John", "Bob"],
"salary": [80000, 60000, 55000]
})
# 取得特定的列
print(data)
print("==============")
print(data.iloc[1]) # 印出第二列
→
name salary
0 Amy 80000
1 John 60000
2 Bob 55000
==============
name John
salary 60000
Name: 1, dtype: object
# 載入 Pandas 模組
import pandas as pd
# 以列表資料為底,建立 Series
pd.Series(資料列表)
內建索引
# 載入 Pandas 模組
import pandas as pd
# 以列表資料為底,建立 Series
pd.Series(資料列表)
自訂索引
# 載入 Pandas 模組
import pandas as pd
# 以列表資料為底,建立 Series
pd.Series(資料列表, index = 索引列表)
資料型態
import pandas as pd
data = pd.Series(資料列表)
# 印出 dtype 屬性
print(data.dtype)
資料數量
import pandas as pd
data = pd.Series(資料列表)
# 印出 size 屬性
print(data.size)
資料索引
import pandas as pd
data = pd.Series(資料列表, index = 索引列表)
# 印出 index 屬性
print(data.index)
根據順序取值
import pandas as pd
data = pd.Series(資料列表)
# 取得資料 data[順序]
print(data.[1])
根據索引取值
import pandas as pd
data = pd.Series(資料列表, index = 索引列表)
# 取得資料 data[索引]
print(data.[索引])
數學、統計相關
import pandas as pd
data = pd.Series([3, 10, 20, 5, -12])
# 各種數學、統計運算
print(data.sum(), data.max(), data.prod())
print(data.mean(), data.median(), data.std())
print(data.nlargest(n), data.nsmallest(n))
-
sum:加法總和
-
max:找最大值
-
prod:乘法總和
-
mean:算算術平均數
-
median:中位數
-
std:標準差
-
nlargest(n):取前 n 大的數字
-
nsmallest(n):取最小的 n 個數字
字串操作相關
import pandas as pd
data = pd.Series("酷啦", "Python", "Pandas")
# 各種字串操作,都定義在 str 底下
print(data.str.lower(), data.str.upper(), data.str.len())
print(data.str.cat(sep = ", "), data.str.contains("P"))
print(data.str.replace("Hello", "你好嗎"))
-
lower:把所有字串變成小寫
-
upper:把所有字串變成大寫
-
len:取得字串長度
-
cat(sep = ", ")
:用逗號把字串串在一起 -
contains("P")
:看字串是否包含大寫的P -
replace("Hello", "你好嗎")
:將字串進行取代,把 Hello 取代成你好嗎,把字串做取代的運算
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series([5, 4, -2, 3, 7])
print(data)
→
0 5
1 4
2 -2
3 3
4 7
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series([5, 4, -2, 3, 7], index = ["a", "b", "c", "d", "e"])
print(data)
→
a 5
b 4
c -2
d 3
e 7
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series([5, 4, -2, 3, 7], index = ["a", "b", "c", "d", "e"])
# 觀察資料
print("資料型態", data.dtype)
print("資料數量", data.size)
print("資料索引", data.index)
→
資料型態 int64
資料數量 5
資料索引 Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series([5, 4, -2, 3, 7], index = ["a", "b", "c", "d", "e"])
# 取得資料:根據順序、根據索引
print(data[2], data[0]) # 根據順序
print(data["e"], data["d"]) # 根據索引
→
-2 5
7 3
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series([5, 4, -2, 3, 7], index = ["a", "b", "c", "d", "e"])
# 數字運算:基本、統計、順序
print("最大值", data.max())
print("總和", data.sum())
print("標準差", data.std())
print("中位數", data.median())
print("最大的三個數", data.nlargest(3)) # nsmallest(2):最小的兩個數
→
最大值 7
總和 17
標準差 3.361547262794322
中位數 4.0
最大的三個數 e 7
a 5
b 4
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series(["酷啦", "Python", "Pandas"])
# 字串運算:基本、串接、搜尋、取代
print(data.str.lower()) # 全部變小寫
→
0 酷啦
1 python
2 pandas
dtype: object
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series(["酷啦", "Python", "Pandas"])
# 字串運算:基本、串接、搜尋、取代
print(data.str.len()) # 算出每個字串的長度
→
0 2
1 6
2 6
dtype: int64
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series(["酷啦", "Python", "Pandas"])
# 字串運算:基本、串接、搜尋、取代
print(data.str.cat(sep = ", ")) # 把字串串起來,可以自訂串接的符號
print(data.str.cat(sep = " - ")) # 把字串串起來,可以自訂串接的符號
→
酷啦, Python, Pandas
酷啦 - Python - Pandas
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series(["酷啦", "Python", "Pandas"])
# 字串運算:基本、串接、搜尋、取代
print(data.str.contains("P")) # 判斷每個字串是否包含特定的字元
→
0 False
1 True
2 True
dtype: bool
# 載入 pandas 模組
import pandas as pd
# 資料索引
data = pd.Series(["酷啦", "Python", "Pandas"])
# 字串運算:基本、串接、搜尋、取代
print(data.str.replace("酷啦", "好胖")) # 將字串中的字元進行替換的動作
→
0 好胖
1 Python
2 Pandas
dtype: object
建立 DataFrame
# 載入 Pandas 模組
import pandas as pd
# 以字典資料為底,建立 DataFrame
pd.DataFrame(字典)
內建索引
# 載入 Pandas 模組
import pandas as pd
# 以字典資料為底,建立 DataFrame
pd.DataFrame(字典)
自訂索引
# 載入 Pandas 模組
import pandas as pd
# 以字典資料為底,建立 DataFrame
pd.DataFrame(字典, index = 索引列表)
資料數量
import pandas as pd
data = pd.DataFrame(字典)
# 印出 size 屬性
print(data.size)
資料形狀
import pandas as pd
data = pd.DataFrame(字典)
# 印出 shape 屬性
print(data.shape)
資料索引
import pandas as pd
data = pd.DataFrame(資料列表, index = 索引列表)
# 印出 index 屬性
print(data.index)
根據順序取一整列
import pandas as pd
data = pd.DataFrame(字典)
# 取得一整列 data.iloc[順序]
print(data.iloc[列編號]) # Series 型態
根據索引取一整列
import pandas as pd
data = pd.DataFrame(字典, index = 索引列表)
# 取得一整列 data.loc[順序]
print(data.loc[索引]) # Series 型態
根據名稱取一整欄
import pandas as pd
data = pd.DataFrame(字典)
# 取得一整欄 data[欄位名稱] ex. A、B、C
print(data[欄位名稱]) # Series 型態 (代表 Series 運算可以直接使用)
建立新的欄位
import pandas as pd
data = pd.DataFrame(字典)
# 以下語法建立新的欄位
data["新欄位名稱"] = 列表資料
data["新欄位名稱"] = Series 型態資料
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
})
print(data)
→
name salary
0 Amy 30000
1 Bob 60000
2 Charles 45000
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 觀察資料
print("資料數列", data.size)
print("資料形狀 (列、欄)", data.shape)
print("資料索引", data.index)
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
資料數列 6
資料形狀 (列、欄) (3, 2)
資料索引 Index(['a', 'b', 'c'], dtype='object')
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 取得列 (Row / 橫向) 的 Series 資料:根據順序、根據索引
print("取得第二列", data.iloc[1], sep = "\n")
print("========================================")
print("取得第c列", data.loc["c"], sep = "\n")
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
取得第二列
name Bob
salary 60000
Name: b, dtype: object
========================================
取得第 c 列
name Charles
salary 45000
Name: c, dtype: object
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
},index=["a", "b", "c"])
print(data)
print("========================================")
# 取得欄 (Column / 直向) 的 Series 資料:根據欄位的名稱
print("取得 name 欄位", data["name"], sep = "\n")
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
取得 name 欄位
a Amy
b Bob
c Charles
Name: name, dtype: object
雙維度的資料,在取得特定的欄或列,會變成單維度的資料 (Series)
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 取得欄 (Column / 直向) 的 Series 資料:根據欄位的名稱
names = data["name"] # 取得單維度的 Series 資料
print("把 name 全部轉大寫", names.str.upper(), sep = "\n")
# 計算薪水的平均值
salaries = data["salary"]
print("薪水的平均值", salaries.mean())
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
把 name 全部轉大寫
a AMY
b BOB
c CHARLES
Name: name, dtype: object
薪水的平均值 45000.0
建立新的欄位
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 建立新的欄位
data["revenue"] = [5000000, 4000000, 3000000] # data[新欄位的名稱] = 列表
data["rank"] = pd.Series([3, 6, 1], index = ["a", "b", "c"]) # data[新欄位的名稱] = Series 的資料 (較正式的寫法)
print(data)
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
name salary revenue rank
a Amy 30000 5000000 3
b Bob 60000 4000000 6
c Charles 45000 3000000 1
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 建立新的欄位
data["revenue"] = [5000000, 4000000, 3000000] # data[新欄位的名稱] = 列表
data["rank"] = pd.Series([3, 6, 1], index = ["a", "b", "c"]) # data[新欄位的名稱] = Series 的資料
data["cp"] = data["salary"]
print(data)
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
name salary revenue rank cp
a Amy 30000 5000000 3 30000
b Bob 60000 4000000 6 60000
c Charles 45000 3000000 1 45000
# 載入 pandas 模組
import pandas as pd
# 資料索引:pd.DataFrame(字典, index = 索引列表)
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
}, index = ["a", "b", "c"])
print(data)
print("========================================")
# 建立新的欄位
data["revenue"] = [5000000, 4000000, 3000000] # data[新欄位的名稱] = 列表
data["rank"] = pd.Series([3, 6, 1], index = ["a", "b", "c"]) # data[新欄位的名稱] = Series 的資料
data["cp"] = data["revenue"] / data["salary"]
print(data)
→
name salary
a Amy 30000
b Bob 60000
c Charles 45000
========================================
name salary revenue rank cp
a Amy 30000 5000000 3 166.666667
b Bob 60000 4000000 6 66.666667
c Charles 45000 3000000 1 66.666667
-
單維度的資料 Series
-
雙維度的資料 DataFrame
基本邏輯
# 建立 Series 資料
import pandas as pd
data = pd.Series(列表)
# 建立篩選條件 (與資料數量對應的布林值)
condition = [True, False, True] # 要第一個和第三個資料,不要第二個資料
# 根據條件完成篩選
filteredData = data[condition]
常見操作
# 建立 Series 資料
import pandas as pd
data = pd.Series(列表)
# 建立篩選條件 (直接透過比較運算產生)
condition = data > 5
# 根據條件完成篩選
filteredData = data[condition]
基本邏輯
# 建立 DataFrame 資料
import pandas as pd
data = pd.Series(字典)
# 建立篩選條件 (與資料列數量對應的布林值) # 篩選橫向資料(列)
condition = [True, False, True] # 要第一列和第三列不要第二列
# 根據條件完成篩選
filteredData = data[condition]
常見操作
# 建立 DataFrame 資料
import pandas as pd
data = pd.Series(字典)
# 建立篩選條件 (透過特定欄位的比較運算產生)
condition = data[欄位名稱] > 5
# 根據條件完成篩選
filteredData = data[condition]
基本寫法,較無彈性
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - Series
data = pd.Series([30, 15, 20])
condition = [True, False, True]
filteredData = data[condition]
print(filteredData)
→
0 30
2 20
dtype: int64
常見操作:比較運算
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - Series
data = pd.Series([30, 15, 20])
condition = data > 18
print(condition)
print("========================================")
filteredData = data[condition]
print(filteredData)
→
0 True
1 False
2 True
dtype: bool
========================================
0 30
2 20
dtype: int64
基本寫法,較無彈性
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - Series
data = pd.Series(["酷啦", "Python", "Pandas"])
condition = [False, True, True]
filteredData = data[condition]
print(filteredData)
→
1 Python
2 Pandas
dtype: object
常見操作:比較運算
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - Series
data = pd.Series(["酷啦", "Python", "Pandas"])
condition = data.str.contains("P")
print(condition)
print("========================================")
filteredData = data[condition]
print(filteredData)
→
0 False
1 True
2 True
dtype: bool
========================================
1 Python
2 Pandas
dtype: object
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - DataFrame
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
})
print(data)
→
name salary
0 Amy 30000
1 Bob 60000
2 Charles 45000
基本寫法
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - DataFrame
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
})
condition = [False, True, True]
filteredData = data[condition]
print(filteredData)
→
name salary
1 Bob 60000
2 Charles 45000
常見操作:比較運算
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - DataFrame
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
})
condition = data["salary"] >= 40000
print(condition)
print("========================================")
filteredData = data[condition]
print(filteredData)
→
0 False
1 True
2 True
Name: salary, dtype: bool
========================================
name salary
1 Bob 60000
2 Charles 45000
# 載入 pandas 模組
import pandas as pd
# 篩選練習 - DataFrame
data = pd.DataFrame({
"name": ["Amy", "Bob", "Charles"],
"salary": [30000, 60000, 45000]
})
condition = data["name"] == "Amy"
print(condition)
print("========================================")
filteredData = data[condition]
print(filteredData)
→
0 True
1 False
2 False
Name: name, dtype: bool
========================================
name salary
0 Amy 30000
-
收集資料:利用程式自動收集想要的資料
-
清理資料:利用程式清理原始資料中不乾淨的東西
-
資料分析:描述統計、推論統計等等
-
基於資料的應用
下載 http://bit.ly/2UMcbDI 中的 csv 檔案並放入專案資料夾 (練習用的 Python 資料夾)
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame (資料是 csv;檔案在專案資料夾的根目錄,所以可以直接寫檔案名稱)
# 觀察資料
print(data)
→
App ... Android Ver
0 Photo Editor & Candy Camera & Grid & ScrapBook ... 4.0.3 and up
1 Coloring book moana ... 4.0.3 and up
2 U Launcher Lite – FREE Live Cool Themes, Hide ... ... 4.0.3 and up
3 Sketch - Draw & Paint ... 4.2 and up
4 Pixel Draw - Number Art Coloring Book ... 4.4 and up
... ... ... ...
10836 Sya9a Maroc - FR ... 4.1 and up
10837 Fr. Mike Schmitz Audio Teachings ... 4.1 and up
10838 Parkinson Exercices FR ... 2.2 and up
10839 The SCP Foundation DB fr nn5n ... Varies with device
10840 iHoroscope - 2018 Daily Horoscope & Astrology ... Varies with device
[10841 rows x 13 columns]
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:評分的各種統計數據
print(data["Rating"])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
0 4.1
1 3.9
2 4.7
3 4.5
4 4.3
...
10836 4.5
10837 5.0
10838 NaN
10839 4.5
10840 4.5
Name: Rating, Length: 10841, dtype: float64
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:評分的各種統計數據
print("平均數", data["Rating"].mean())
print("中位數", data["Rating"].median())
print("取得前一百個應用程式的平均", data["Rating"].nlargest(100).mean())
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
平均數 4.193338315362443
中位數 4.3
取得前一百個應用程式的平均 5.14
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:評分的各種統計數據
condition = data["Rating"] > 5
data = data[condition]
print(data)
print("平均數", data["Rating"].mean())
print("中位數", data["Rating"].median())
print("取得前一百個應用程式的平均", data["Rating"].nlargest(100).mean())
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
App Category Rating Reviews Size Installs Type Price Content Rating Genres Last Updated Current Ver Android Ver
10472 Life Made WI-Fi Touchscreen Photo Frame 1.9 19.0 3.0M 1,000+ Free 0 Everyone NaN February 11, 2018 1.0.19 4.0 and up NaN
平均數 19.0
中位數 19.0
取得前一百個應用程式的平均 19.0
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:評分的各種統計數據
condition = data["Rating"] <= 5
data = data[condition]
print("平均數", data["Rating"].mean())
print("中位數", data["Rating"].median())
print("取得前一百個應用程式的平均", data["Rating"].nlargest(100).mean())
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
平均數 4.191757420456972
中位數 4.3
取得前一百個應用程式的平均 5.0
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:評分的各種統計數據
condition = data["Rating"] <= 5
data = data[condition]
print("平均數", data["Rating"].mean())
print("中位數", data["Rating"].median())
print("取得前一百個應用程式的平均", data["Rating"].nlargest(1000).mean())
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
平均數 4.191757420456972
中位數 4.3
取得前一百個應用程式的平均 4.823
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
print("平均數", data["Installs"].mean())
→
跑出一堆數字
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
print(data["Installs"])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
0 10,000+
1 500,000+
2 5,000,000+
3 50,000,000+
4 100,000+
...
10836 5,000+
10837 100+
10838 1,000+
10839 1,000+
10840 10,000,000+
Name: Installs, Length: 10841, dtype: object
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量",data.shape)
print("資料欄位",data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
data["Installs"]=pd.to_numeric(data["Installs"])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
Traceback (most recent call last):
File "pandas\_libs\lib.pyx", line 2305, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "10,000+"
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\Python-training\29_pandas-googleplay.py", line 19, in <module>
data["Installs"]=pd.to_numeric(data["Installs"])
File "C:\Users\charmy\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\tools\numeric.py", line 183, in to_numeric
values, _ = lib.maybe_convert_numeric(
File "pandas\_libs\lib.pyx", line 2347, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "10,000+" at position 0
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", ""))
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
D:\Python-training\29_pandas-googleplay.py:19: FutureWarning: The default value of regex will change from True to False in a future version.
data["Installs"]=pd.to_numeric(data["Installs"].str.replace("[,+]",""))
Traceback (most recent call last):
File "pandas\_libs\lib.pyx", line 2305, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "Free"
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "D:\Python-training\29_pandas-googleplay.py", line 19, in <module>
data["Installs"]=pd.to_numeric(data["Installs"].str.replace("[,+]",""))
File "C:\Users\charmy\AppData\Local\Programs\Python\Python310\lib\site-packages\pandas\core\tools\numeric.py", line 183, in to_numeric
values, _ = lib.maybe_convert_numeric(
File "pandas\_libs\lib.pyx", line 2347, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "Free" at position 10472
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
print(data["Installs"][10472])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
Free
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "").replace("Free", ""))
print(data["Installs"])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
D:\Python-training\29_pandas-googleplay.py:19: FutureWarning: The default value of regex will change from True to False in a future version.
data["Installs"]=pd.to_numeric(data["Installs"].str.replace("[,+]","").replace("Free",""))
0 10000.0
1 500000.0
2 5000000.0
3 50000000.0
4 100000.0
...
10836 5000.0
10837 100.0
10838 1000.0
10839 1000.0
10840 10000000.0
Name: Installs, Length: 10841, dtype: float64
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "").replace("Free", ""))
print("平均數", data["Installs"].mean())
condition = data["Installs"] > 100000
print("安裝數量大於 100000 的應用程式有幾個", data[condition].shape)
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
D:\Python-training\29_pandas-googleplay.py:19: FutureWarning: The default value of regex will change from True to False in a future version.
data["Installs"]=pd.to_numeric(data["Installs"].str.replace("[,+]","").replace("Free",""))
平均數 15464338.882564576
安裝數量大於 100000 的應用程式有幾個 (4950, 13)
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 分析資料:安裝數量的各種統計數據
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "").replace("Free", ""))
print("平均數", data["Installs"].mean())
condition = data["Installs"] > 100000
print("安裝數量大於 100000 的應用程式有幾個", data[condition].shape[0]) # shape[0] 類似 Tuple (列表)
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
D:\Python-training\29_pandas-googleplay.py:19: FutureWarning: The default value of regex will change from True to False in a future version.
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "").replace("Free", ""))
平均數 15464338.882564576
安裝數量大於 100000 的應用程式有幾個 4950
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 基於資料的應用:關鍵字搜尋應用程式名稱
keyword = input("請輸入關鍵字:")
condition = data["App"].str.contains(keyword)
print(data[condition])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
請輸入關鍵字:game enter
App ... Android Ver
728 Free intellectual training game application | ... 4.4 and up
884 Low Poly – Puzzle art game ... 4.1 and up
908 VRV: Anime, game videos & more ... Varies with device
955 PlayKids - Educational cartoons and games for ... ... Varies with device
1810 Word Crossy - A crossword game ... 4.0.3 and up
1937 Cover Fire: offline shooting games for free ... 4.1 and up
1965 Quiz: Logo game ... 4.0.3 and up
2020 Super ABC! Learning games for kids! Preschool ... ... 4.1 and up
2036 Number Counting games for toddler preschool kids ... Varies with device
2065 Super ABC! Learning games for kids! Preschool ... ... 4.1 and up
2070 Baby ABC in box! Kids alphabet games for toddl... ... 4.1 and up
2098 Extreme Racing 2 - Real driving RC cars game! ... 4.1 and up
2102 Car Racing game for Kids - Beepzz Dogs 🐕 ... 4.2 and up
2103 Pony Friends 🦄 - Beepzz racing game for kids ... 4.2 and up
2172 World Racers family board game ... 5.1 and up
2175 Whoowasit? - Best kids game! ... 4.1 and up
2207 PlayKids - Educational cartoons and games for ... ... Varies with device
4146 Gangstar Vegas - mafia game ... Varies with device
4393 Dual N-Back - Brain game ... 4.1 and up
4878 Math games for kids : times tables - AB Math ... 4.0.3 and up
4882 Math games for kids : times tables training ... 4.0.3 and up
5011 AE Gun Ball: arcade ball games ... 2.2 and up
5413 Princess Closet : Otome games free dating sim ... 4.0.3 and up
5525 Grow Stone Online : 2d pixel RPG, MMORPG game ... 4.0.3 and up
6094 BF games ... 4.0.3 and up
6140 Board Game Stats: Play tracking for tabletop g... ... 4.1 and up
6335 BJ card game blackjack ... 2.3 and up
6811 Bu the Baby Bunny - Cute pet care game ... 4.1 and up
6824 Pu - Cute giant panda bear, baby pet care game ... 4.1 and up
7643 Them Bombs: co-op board game play with 2-4 fri... ... 4.1 and up
8617 Destiny Ninja Shall we date otome games love s... ... 4.0 and up
9400 RUN JUMP RUN-fun games for free ... 3.0 and up
9583 Shoot`Em Down: Shooting game ... 4.1 and up
9668 Free games: Masha and the Bear ... 4.1 and up
9677 Masha and The Bear Jam Day Match 3 games for kids ... 4.1 and up
10024 No Pimple - Fun games ... 2.3 and up
10165 EZ game screen recorder with audio 1080P ... 5.0 and up
10505 Offroad drive : 4x4 driving game ... 4.1 and up
[38 rows x 13 columns]
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 基於資料的應用:關鍵字搜尋應用程式名稱
keyword = input("請輸入關鍵字:")
condition = data["App"].str.contains(keyword)
print(data[condition]["App"])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
請輸入關鍵字:game enter
728 Free intellectual training game application |
884 Low Poly – Puzzle art game
908 VRV: Anime, game videos & more
955 PlayKids - Educational cartoons and games for ...
1810 Word Crossy - A crossword game
1937 Cover Fire: offline shooting games for free
1965 Quiz: Logo game
2020 Super ABC! Learning games for kids! Preschool ...
2036 Number Counting games for toddler preschool kids
2065 Super ABC! Learning games for kids! Preschool ...
2070 Baby ABC in box! Kids alphabet games for toddl...
2098 Extreme Racing 2 - Real driving RC cars game!
2102 Car Racing game for Kids - Beepzz Dogs 🐕
2103 Pony Friends 🦄 - Beepzz racing game for kids
2172 World Racers family board game
2175 Whoowasit? - Best kids game!
2207 PlayKids - Educational cartoons and games for ...
4146 Gangstar Vegas - mafia game
4393 Dual N-Back - Brain game
4878 Math games for kids : times tables - AB Math
4882 Math games for kids : times tables training
5011 AE Gun Ball: arcade ball games
5413 Princess Closet : Otome games free dating sim
5525 Grow Stone Online : 2d pixel RPG, MMORPG game
6094 BF games
6140 Board Game Stats: Play tracking for tabletop g...
6335 BJ card game blackjack
6811 Bu the Baby Bunny - Cute pet care game
6824 Pu - Cute giant panda bear, baby pet care game
7643 Them Bombs: co-op board game play with 2-4 fri...
8617 Destiny Ninja Shall we date otome games love s...
9400 RUN JUMP RUN-fun games for free
9583 Shoot`Em Down: Shooting game
9668 Free games: Masha and the Bear
9677 Masha and The Bear Jam Day Match 3 games for kids
10024 No Pimple - Fun games
10165 EZ game screen recorder with audio 1080P
10505 Offroad drive : 4x4 driving game
Name: App, dtype: object
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 基於資料的應用:關鍵字搜尋應用程式名稱
keyword=input("請輸入關鍵字:")
condition = data["App"].str.contains(keyword)
print("包含關鍵字的應用程式數量", data[condition].shape[0])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
請輸入關鍵字:game enter
包含關鍵字的應用程式數量 38
import pandas as pd
# 讀取資料
data = pd.read_csv("googleplaystore.csv") # 把 csv 格式的檔案讀取成一個 DataFrame
# 觀察資料
print("資料數量", data.shape)
print("資料欄位", data.columns)
print("========================================")
# 基於資料的應用:關鍵字搜尋應用程式名稱
keyword = input("請輸入關鍵字:")
condition = data["App"].str.contains(keyword, case = False)
print("包含關鍵字的應用程式數量", data[condition].shape[0])
→
資料數量 (10841, 13)
資料欄位 Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type',
'Price', 'Content Rating', 'Genres', 'Last Updated', 'Current Ver',
'Android Ver'],
dtype='object')
========================================
請輸入關鍵字:game enter
包含關鍵字的應用程式數量 257
在分析資料中,data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", ""))
的動作會讓 TERMINAL 裡出現
D:\Python-training\29_pandas-googleplay.py:19: FutureWarning: The default value of regex will change from True to False in a future version.
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", ""))
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "", regex = True))
data["Installs"] = pd.to_numeric(data["Installs"].str.replace("[, +]", "", regex = True).replace("Free", "", regex = True))
-
使用 email.message 模組建立內容
-
使用 smtplib 模組發送信件
-
驗證寄件人身分:帳號密碼/兩階段驗證
import email.message
import email.message
# 建立訊息物件
msg = email.message.EmailMessage()
# 利用訊息物件建立基本設定
msg["From"] = "寄件人地址"
msg["To"] = "收件人地址"
msg["Subject"] = "電子郵件主題(標題)"
import email.message
msg = email.message.EmailMessage()
msg["From"] = "寄件人地址"
msg["To"] = "收件人地址"
msg["Subject"] = "電子郵件主題(標題)"
# 加入純文字內容
msg.set_content("文字內容")
import email.message
msg = email.message.EmailMessage()
msg["From"] = "寄件人地址"
msg["To"] = "收件人地址"
msg["Subject"] = "電子郵件主題(標題)"
# 加入 HTML 內容
msg.add_alternative("<h1>HTML 內容</h1>", subtype = "html")
import smtplib
import smtplib
# 可以從網路上找到主機名稱和連接埠號
server = smtplib.SMTP_SSL("主機名稱", 連線埠號)
import smtplib
server = smtplib.SMTP_SSL("主機名稱", 連線埠號)
# 根據連線的伺服器,輸入對應的帳號密碼
server.login("帳號", "密碼")
import smtplib
server = smtplib.SMTP_SSL("主機名稱", 連線埠號)
server.login("帳號", "密碼")
# msg 變數存放上一個步驟準備好的訊息物件
server.send_message(msg)
server.close() # 發送完成後關閉連線
-
Chrome 搜尋 google 帳戶並打開該網頁 (Google 帳戶)
-
登入
-
安全性→找到低安全性應用程式存取權 (需開啟)
-
若帳戶有開啟兩步驟認證
-
點選產生應用程式密碼
-
郵件
-
Windows電腦 (視裝置而定),也可用其他自行設定 (Python Program),此動作只是一個標示而已,可隨便輸入
-
產生
-
記住產生的密碼 (只會出現一次),此密碼隨時可以刪出及產生新的,此密碼可以當作登入帳號的密碼,覺得不安全可以刪掉
# 寄送 Email 的程式
# 準備訊息物件設定
import email.message
msg = email.message.EmailMessage()
msg["From"] = "寄件人地址"
msg["To"] = "收件人地址"
msg["Subject"] = "電子郵件主題(標題)"
# 寄送純文字的內容
msg.set_content("測試")
# 寄送比較多樣式的內容 (HTML)
msg.add_alternative("<h1>HTML 內容</h1>", subtype = "html")
# 連線到 SMTP Server,驗證寄件人身份並發送郵件
import smtplib
# 到網路上查詢 gmail smtp server 或是 yahoo smtp server
server = smtplib.SMTP_SSL("smtp.gmail.com",465)
server.login("帳號", "密碼")
server.send_message(msg)
server.close()
# 寄送 Email 的程式
# 準備訊息物件設定
import email.message
msg = email.message.EmailMessage()
msg["From"] = "charmytseng0118@gmail.com"
msg["To"] = "echarmy0118@gmail.com"
msg["Subject"] = "酷啦皮卡丘"
# 寄送純文字的內容
msg.set_content("測試")
# 連線到 SMTP Server,驗證寄件人身份並發送郵件
import smtplib
# 到網路上查詢 gmail smtp server 或是 yahoo smtp server
server = smtplib.SMTP_SSL("smtp.gmail.com", 465)
server.login("charmytseng0118@gmail.com", "charmytseng0118@gmail.com 的密碼")
server.send_message(msg)
server.close()
# 寄送 Email 的程式
# 準備訊息物件設定
import email.message
msg = email.message.EmailMessage()
msg["From"] = "charmytseng0118@gmail.com"
msg["To"] = "echarmy0118@gmail.com"
msg["Subject"] = "酷啦皮卡丘"
# 寄送比較多樣式的內容 (HTML)
msg.add_alternative("<h1>HTML內容</h1>", subtype="html")
# 連到 SMTP Server,驗證寄件人身份並發送郵件
import smtplib
# 到網路上查詢 gmail smtp server 或是 yahoo smtp server
server = smtplib.SMTP_SSL("smtp.gmail.com",465)
server.login("charmytseng0118@gmail.com", "CharmyKing0118Tseng")
server.send_message(msg)
server.close()
-
字串 (String):可以把字串中的字元分開、逐一取出
- ex. "Hello"
-
列表 (List):可以把列表中的資料分開、逐一取出
- ex. [3, 4, 2]
-
集合 (Set):可以把集合中的資料分開、逐一取出
- ex. {100, 1, 5}
-
字典 (Dictionary):可以把字典中的 Key 分開、逐一取出
- ex. {"a": 3, "x": 4}
基本語法
for 變數名稱 in 列表或字串:
將列表中的資料或字串中的字元,逐一取出
語法進階說明
for 變數名稱 in 可疊代的資料:
將可疊代的資料分開,逐一取出
回傳最大值
max(可疊代的資料)
回傳排序後的列表
sorted(可疊代的資料)
字串 (String)
# for 變數名稱 in 可疊代的資料:
for x in "abc":
print(x)
→
a
b
c
列表 (List)
# for 變數名稱 in 可疊代的資料:
for x in [3, 5, 2]:
print(x)
→
3
5
2
集合 (Set)
# for 變數名稱 in 可疊代的資料:
for x in {"a", "test", 3, 10}:
print(x)
→
10
3
a
test
字典 (Dictionary)
# for 變數名稱 in 可疊代的資料:
for x in {"a", "test", 3, 10}:
print(x)
→
10
3
a
test
# for 變數名稱 in 可疊代的資料:
dic = {"a": 3, "x": 5}
for key in dic:
print(key)
print(dic[key])
→
a
3
x
5
max(可疊代資料)
# max(可疊代資料)
result = max([10, 2, 30, 1])
print(result)
result = max("xaz")
print(result)
result = max({10, 200, 30, 1})
print(result)
result = max({"x": 3, "a": 4})
print(result)
→
30
z
200
x
sorted(可疊代資料)
# sorted(可疊代資料)
result = sorted("cab")
print(result)
result = sorted({10, 2, 100, -5})
print(result)
→
['a', 'b', 'c']
[-5, 2, 10, 100]
基本語法
yield 資料
def 函式名稱():
yield 資料
# 呼叫函式,回傳生成器
變數名稱 = 函式名稱()
程式範例
def test():
yield 3
# 呼叫函式,回傳生成器
gen = test()
print(gen)
語法說明
for 變數名稱 in 可疊代的資料:
將可疊代的資料分開,逐一取出
for 變數名稱 in 生成器:
將生成器產生的資料,逐一取出
搭配使用範例
def test():
yield 3
# 呼叫函式,回傳生成器
gen = test()
# 搭配 for 迴圈使用
for data in gen:
print(data)
def test():
yield 3
yield 5
# 呼叫函式,回傳生成器
gen = test()
# 搭配 for 迴圈使用,逐一印出 3 和 5
for data in gen:
print(data)
# 定義建立生成器函式
def test():
yield 5
# 呼叫並回傳生成器
gen = test()
print(gen)
→
<generator object test at 0x000001D493E39A10>
# 定義建立生成器函式
def test():
yield 5
# 呼叫並回傳生成器
gen = test()
# 搭配for迴圈中使用
for d in gen:
print(d) # 印出 5
→
5
# 定義建立生成器函式
def test():
print("階段一")
yield 5
print("階段二")
yield 10
# 呼叫並回傳生成器
gen = test()
→
沒有跑出任何東西
只要函式中有 yield,就和傳統的函式呼叫不同 (傳統函式呼叫:呼叫函式就會執行函式內的程式碼);函式中有 yield,就會先建立生成器,函式中的程式碼暫時不會動,若想動函式中的程式碼,則需搭配 for 迴圈
# 定義建立生成器函式
def test():
print("階段一")
yield 5
print("階段二")
yield 10
# 呼叫並回傳生成器
gen = test()
# 搭配 for 迴圈中使用
for d in gen:
print(d)
→
階段一
5
階段二
10
-
for d in gen:
-
跑第一圈時就會去看函式程式碼開始執行
-
印出階段一
-
yield 5 被放進 d 裡面後印出 5
-
從剛剛 yield 的位置 (yield 5) 繼續往下跑
-
印出階段二
-
yield 10 被放進 d 裡面後印出 10
-
yield 10 後沒有其他資料,迴圈結束
產生偶數
def generateEven(): # generate:產生;even:偶數
number = 0
yield number
number += 2
yield number
number += 2
yield number
evenGenerator = generateEven()
for data in evenGenerator:
print(data)
→
0
2
4
產生無限多偶數
def generateEven():
number = 0
while True:
yield number
number += 2
evenGenerator = generateEven()
for data in evenGenerator:
print(data)
→
產生無限多偶數
def generateEven(maxNumber):
number = 0
while number <= maxNumber:
yield number
number += 2
evenGenerator = generateEven(10)
for data in evenGenerator:
print(data)
→
0
2
4
6
8
10
def generateEven(maxNumber):
number = 0
while number <= maxNumber:
yield number
number += 2
evenGenerator = generateEven(16)
for data in evenGenerator:
print(data)
→
0
2
4
6
8
10
12
14
16
程式範例
def test(arg):
print(arg)
# 呼叫 test,傳遞函式
test(3)
test("Hello")
程式範例
def test(arg):
print(arg)
# 建立另一個函式 handle
def handle():
print(100)
# 呼叫 test,傳遞函式
test(handle)
程式範例
def test(arg):
arg() # 呼叫回呼函式
def handle():
print(100)
test(handle)
-
呼叫 test
-
把 handle 傳遞到 test 的 arg 裡面(arg 變成一個函式)
-
arg 後面加 () 就叫呼叫回呼函式 (呼叫到 handle 裡面)
-
整個程式最後會印出 100
程式範例
def test(arg):
arg(50) # 回呼函式的參數
def handle(data):
print(data)
test(handle)
-
從最後一行開始看
-
呼叫函式 test,把 handle 函式傳遞到 arg 裡面 (arg 就是 handle)
-
呼叫 arg (就是呼叫回呼函式)
-
把 50 放進去 (回呼函式的參數)
-
50 放進去就是放到 handle 的 data 裡面 (50 傳遞到data 裡面)
-
print 印出 50
def test(arg):
print(arg)
test(3)
test("Hello")
→
3
Hello
def test(arg):
print(arg)
def handle():
print(100)
test(handle)
→
<function handle at 0x000002438018E950>
def test(arg):
arg() # 函式呼叫
# 定義一個回呼函式
def handle():
print(100)
test(handle)
→
100
def test(arg):
arg("Hello") # 呼叫回呼函式,帶入參數
# 定義一個回呼函式
def handle(da):
print(da)
test(handle)
→
Hello
def add(n1, n2):
print(n1 + n2)
add(3, 4)
→
7
def add(n1, n2, cb):
cb(n1 + n2)
def handle1(result):
print("結果是", result)
add(3, 4, handle1)
add(5, 6, handle1)
→
結果是 7
結果是 11
def add(n1, n2, cb):
cb(n1 + n2)
def handle1(result):
print("結果是", result)
def handle2(result):
print("Result of Add is", result)
add(3, 4, handle1)
add(5, 6, handle1)
add(4, 2, handle2)
→
結果是 7
結果是 11
Result of Add is 6
- 裝飾器本質上是一個函式,用來輔助其他函式的運作
定義裝飾器
def 裝飾器名稱(回呼函式名稱):
def 內部函式名稱():
# 裝飾器內部的程式碼
回呼函式名稱()
return 內部函式名稱
使用裝飾器
@裝飾器名稱
def 函式名稱():
# 函式內部的程式碼
函式名稱() # 呼叫帶有裝飾器的函式
程式範例
def testDecorator(callback):
def innerFunc():
print("裝飾器")
callback()
return innerFunc
@testDecorator
def decoratedFunc():
print("普通函式")
decoratedFunc()
-
上面是自己定義的裝飾器,裝飾器名字叫做 testDecorator,此裝飾器內部要執行的程式碼用裝飾器三個字把它印出來
-
下面是使用裝飾器,定義一個普通函式取名叫 decoratedFunc,在普通函式上面加上@裝飾器名稱,形成帶有裝飾器的函式
-
最後呼叫帶有裝飾器的函式 decoratedFunc
-
先執行裝飾器內部函式的程式碼,所以會先印出裝飾器三個字,呼叫 callback (呼叫回呼函式)
-
回呼函式就是本來的函式
-
回呼函式呼叫回來印出普通函式 4 個字
-
要呼叫一個有裝飾器的函式 (decoratedFunc)
-
就不會執行函式內的程式碼 (普通函式)
-
會被直接丟到回呼函式裡面 (decoratedFunc 被丟到 callback 裡面)
-
先執行裝飾器中的內部函式,印出裝飾器
-
在呼叫回呼函式
-
然後才呼叫回本來的函式中,印出普通函式
-
程式結束
程式範例
def testDecorator(callback):
def innerFunc():
print("裝飾器")
callback(3)
return innerFunc
@testDecorator
def decoratedFunc(data):
print("普通函式", data)
decoratedFunc()
-
呼叫一個帶有裝飾器的函式 (decoratedFunc)
-
先去執行裝飾器內部的程式碼,印出裝飾器 3 個字
-
然後呼叫 callback (呼叫 callback 其實就是呼叫 decoratedFunc),所以 decoratedFunc 並不是在最下面呼叫的
# 定義裝飾器
def myDeco(cb):
def run():
print("裝飾器中的程式碼")
cb()
return run
# 使用裝飾器
def test():
print("普通函式的程式碼")
test()
→
普通函式的程式碼
# 定義裝飾器
def myDeco(cb):
def run():
print("裝飾器中的程式碼")
cb()
return run
# 使用裝飾器
@myDeco
def test():
print("普通函式的程式碼")
test()
→
裝飾器中的程式碼
普通函式的程式碼
# 定義裝飾器
def myDeco(cb):
def run():
print("裝飾器中的程式碼")
cb()
return run
# 使用裝飾器
def test(n):
print("普通函式的程式碼", n)
test(3)
→
普通函式的程式碼 3
# 定義裝飾器
def myDeco(cb):
def run():
print("裝飾器中的程式碼")
cb(5) # 這個回呼函式,其實就是被裝飾的普通函式
return run
# 使用裝飾器
@myDeco
def test(n):
print("普通函式的程式碼", n)
test()
→
裝飾器中的程式碼
普通函式的程式碼 5
寫 1 加到 50 的裝飾器
# 定義一個裝飾器,計算 1 + 2 + ... + 50 的總和
def calculate(callback):
def run():
# 裝飾器想要執行的程式碼
result = 0
for n in range(51):
result += n
print(result) # 印出 1 + 2 + ... + 50 的總和
callback()
return run
# 使用裝飾器
@calculate
def show():
print("普通函式的程式碼")
show()
→
1275
普通函式的程式碼
# 定義一個裝飾器,計算 1 + 2 + ... + 50 的總和
def calculate(callback):
def run():
# 裝飾器想要執行的程式碼
result = 0
for n in range(51):
result += n
# 把計算結果透過參數傳到被裝飾的普通函式中
callback(result)
return run
# 使用裝飾器
@calculate
def show(n):
print("計算結果是", n)
show()
→
計算結果是 1275
# 定義一個裝飾器,計算 1 + 2 + ... + 50 的總和
def calculate(callback):
def run():
# 裝飾器想要執行的程式碼
result = 0
for n in range(51):
result += n
# 把計算結果透過參數傳到被裝飾的普通函式中
callback(result)
return run
# 使用裝飾器
@calculate
def show(n):
print("計算結果是", n)
@calculate
def showEnglish(n):
print("Result is", n)
show()
showEnglish()
→
計算結果是 1275
Result is 1275
定義與使用
def裝飾器名稱(回呼函式名稱):
def內部函式名稱():
# 裝飾器內部的程式碼
回呼函式名稱()
return 內部函式名稱
@裝飾器名稱
def 函式名稱():
# 函式內部的程式碼
函式名稱() # 呼叫帶有裝飾器的函式
定義與使用
- 用來生產裝飾器;本身也是函式
定義與使用
def 裝飾器工廠名稱(參數名稱, …):
def 裝飾器名稱(回呼式名稱函):
def 內部函式名稱():
# 裝飾器內部的程式碼
回呼函式名稱()
return 內部函式名稱
return 裝飾器名稱
@裝飾器工廠名稱(參數資料, …)
def 函式名稱():
# 函式內部的程式碼
函式名稱() # 呼叫帶有裝飾器的函式
程式範例
def testFactory(base):
def testDecorator(callback):
def innerFunc():
print("裝飾器", base)
callback()
return innerFunc
return testDecorator
@testFactory(3)
def decoratedFunc():
print("普通函式")
decoratedFunc()
-
定義一個裝飾器工廠叫做 testFactory,接收一個參數名稱叫做 base
-
在裝飾器工廠裡面定義一個裝飾器 testDecorator,其中 callback 為回呼函式
-
內部函式 innerFunc 執行裝飾器的程式碼,印出裝飾器三個字 (可以額外調用在裝飾器工廠裡面傳進來的參數 base,也可以把 base 印出來)
-
呼叫回呼函式
-
記得要 return 裝飾器名稱 (在裝飾器裡面
return innerFunc
)
- 這樣就有裝飾器工廠 testFactory 接收一個參數 base,在普通函式上面加 @ 和裝飾器工廠名稱 testFactory 及對應的參數資料 3,把 3 傳遞到 base 裡面 (base 就是 3),就會產生一個裝飾器讓函式 decoratedFunc 使用,接著呼叫帶有裝飾器的函式,呼叫後先執行裝飾器的程式碼印出裝飾器和 3,在執行普通函式內部的程式碼,印出普通函式,流程運作完畢
程式範例
def testFactory(base):
def testDecorator(callback):
def innerFunc():
result = base * 3
callback(result)
return innerFunc
return testDecorator
@testFactory(3)
def decoratedFunc(result):
print("普通函式", result)
decoratedFunc()
-
裝飾器工廠 testFactory 帶入一個數字 3
-
把這個數字 3 乘以 3
-
再把得到的結果送回普通函式做一個顯示
程式邏輯:testFactory 帶入 3,3 傳到 base 裡面,在執行函式裡面把 base 乘以 3 倍,3 * 3 = 9放進 result,再把結果送到回呼函式 callback 裡面,放到回呼函式的參數,最後印出普通函式 9,也就是裝飾器工廠把參數變 3 倍放到函式中
def myDeco(cb):
def run():
print("裝飾器內的程式")
cb()
return run
@myDeco
def test():
print("普通函式的程式")
test()
→
裝飾器內的程式
普通函式的程式
def myFactory():
def myDeco(cb):
def run():
print("裝飾器內的程式")
cb()
return run
return myDeco
@myFactory()
def test():
print("普通函式的程式")
test()
→
裝飾器內的程式
普通函式的程式
def myFactory(base):
def myDeco(cb):
def run():
print("裝飾器內的程式", base)
cb()
return run
return myDeco
@myFactory(3)
def test():
print("普通函式的程式")
test()
→
裝飾器內的程式 3
普通函式的程式
def myFactory(base):
def myDeco(cb):
def run():
print("裝飾器內的程式", base)
result = base * 2
cb(result)
return run
return myDeco
@myFactory(10)
def test(result):
print("普通函式的程式",result)
test()
→
裝飾器內的程式 10
普通函式的程式 20
# 計算 1 + 2 + 3 + ... + 50 的裝飾器
def calculate(callback):
def run():
total = 0
for n in range(51):
total += n
callback(total)
return run
@calculate
def show(result):
print("計算結果是", result)
@calculate
def showEnglish(result):
print("Result is", result)
show()
showEnglish()
→
計算結果是 1275
Result is 1275
# 計算 1 + 2 + 3 + ... + max 的裝飾器工廠
def calculateFactory(max):
def calculate(callback):
def run():
total = 0
for n in range(max + 1):
total += n
callback(total)
return run
return calculate
@calculateFactory(100)
def show(result):
print("計算結果是", result)
@calculateFactory(10)
def showEnglish(result):
print("Result is", result)
show()
showEnglish()
→
計算結果是 5050
Result is 55