---
# System prepended metadata

title: 2022-11-27 第三天 Python網路爬蟲應用實務班上課記錄
tags: [已轉移]

---

# 2022-11-27 第三天 Python網路爬蟲應用實務班上課記錄
###### tags: `python` `爬蟲`

## 函式
```python=
# 將一組成程式碼集中起來, 可以完成某件事或某個功能, 需要透過"呼叫"的手段來讓函式(或稱為函數)內的程式碼執行
# 1. 函式名稱可以是 數字, 英文大小寫, 底線的組合
# 2. 函式名稱第一個字不可以是數字
# 3. 不可以使用Python保留字
# 4. 可以使用跟內建函式名稱一樣的名字，但你會失去原本函式的功能，所以不建議
# 5. 函式名稱的大小寫視為不同名稱

# 小括號內定義該函式呼叫時要傳入多少個參數, 空的話表示不需要參數(或稱為引數)
def my_first_func():
    print('Hi my function')

my_first_func()   # 函式呼叫

my_first_func()   # 函式呼叫

my_first_func()   # 函式呼叫

# 有個參數的函式
def show_me(name):  # 定一個呼叫時一定要傳入一個參數的函式
    print(f'My name is {name}')  # name參數對於show_me函式來說是一個"內部"變數

show_me('Aaron')  # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數
show_me('Andy')  # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數
show_me('Abner')  # 呼叫show_me函式病傳入Aaron字串作為該函式內的name參數

# 有兩個參數的函式
def compare_num(a1, a2):
    if a1 > a2:
        print(f'{a1} 比 {a2} 大')
    else:
        print(f'{a1} 比 {a2} 小')


compare_num(4, 8)    # 參數傳入函式後會被依照參數的順序擺放
compare_num(48, 23)

# 有三個參數的函式
def three_param(a, b, c):
    print(f'三個參數為: {a}, {b}, {c}')

three_param('Test', 99, True)
```
#### 練習
```python=
# 寫一函式，名稱為 user_input，該函式功能為:
#  1. 接受使用者輸入一個整數參數
#  2. 將該使用者輸入平方後顯示到畫面上
def user_input(num):
    print(f'{num ** 2}')

user_input(20)
user_input(12)
```
#### 參數預設值
```python=
# 參數預設值, 當呼叫函式如果沒有傳入該對應的參數，則直接使用一個預設值作為參數
def show_me(name = '無名氏'):
    print(f'My name is {name}')

show_me('Aaron')
show_me()

# 有參數預設值的參數，右邊的參數全部都要有預設值
def check_num(a, b = -1, c = -1):
    print(f'{a}, {b}, {c}')

check_num(1, 2, 3)
check_num(1)
# check_num()  # 沒有參數預設值就醫定要傳入該參數
check_num(1, 2)

def my_info(name, phone, addr):
    print(f'我的名字叫{name}, 電話是{phone}, 家裡地址{addr}')

my_info(phone='0987654321', addr='台北市某個地方', name='Aaron')   # 透過指定參數名稱的方式來傳入參數
```

#### 回傳值
```python=
# 回傳值

# 函式在執行結束後可以產生資料回傳給呼叫方
def do_plus(a1, a2):
    print(f'總和: {a1 + a2}')
    
    total = a1 + a2

    return total  # 結束函式執行(類似迴圈內的break)，並回傳後面的資料

total = do_plus(2, 3)  # 接收函式回傳值

print(f'接受到回傳值: {total}')  # 注意: 這個total和函式內的total為兩個不同的變數

# 打算把2 + 3的結果作平方
print(f'2和3加總後的平方為: {total ** 2}')
```

#### pack與unpack
```python=
# 寫一函式swap, 可以用來交換兩個變數內的資料
def swap(a, b):
    return b, a   # return 永遠只能回傳一筆資料, 這裡會pack兩筆資料成為一個tuple
   
aa = 99
bb = 88

aa, bb = swap(aa, bb)
print(f'aa = {aa}, bb = {bb}')

c = swap(aa, bb)
print(c, type(c))


# tuple 回憶
a = 3, 4, 5, 6, 7

print(a, type(a))

a, b, c = a   # unpack tuple並存到三個變數內

print(a, b, c)
```

#### 一級函式
```python=
# 一級函式
# Python的函式就是一級函式, 函式本身就是一個物件(資料), 可以被存到變數內

def show_me(name):
    print(f'My name is {name}')

# a = show_me()  這個是把show_me函式的回傳值存到a變數
a = show_me  # 將show_me函式本體存到a變數

a('Aaron')

def do_plus(a, b):
    return a + b

def do_miner(a, b):
    return a - b

def do_mux(a, b):
    return a * b

def do_div(a, b):
    return a / b

a = 10
b = 5

print(   do_plus(a, b)    )   # 一行程式碼有多個函式, 其呼叫順序為由內到外
print(   do_miner(a, b)   )
print(   do_mux(a, b)     )
print(   do_div(a, b)     )

def do_math(do_func, a, b):
    return do_func(a, b)

print(   do_math(do_plus, a, b)    )   # 一行程式碼有多個函式, 其呼叫順序為由內到外
print(   do_math(do_miner, a, b)   )
print(   do_math(do_mux, a, b)     )
print(   do_math(do_div, a, b)     )
```

#### callable()
```python=
# callable() Python內建函式, 用來偵測某個變數內是不是函式, True=是函式, False=不是函式

def show():
    print('Show')

a = 2
print(   callable(a)  )

a = show
print(   callable(a)   )


if callable(a) == True:
    a()
else:
    print(a)
```

#### lambda函式
```python=
# LAMBDA 定義函式, 定義出來的函式"只有一行", 而且沒有名字
# def show(a, b):
#     print(a, b)

# lambda定義完後可以直接呼叫  
(lambda a, b: print(a, b))(2, 'Hi')

# show(1, 'Hi')


# 範例
def max(a1, a2):
    # if a1 > a2:
    #     return a1
    # else:
    #     return a2

    return a1 if a1 > a2 else a2

print(max(5, 6))
print(max(15, 9))
print(max(99, 54))

max2 = lambda a1, a2: a1 if a1 > a2 else a2  # 不需要加上return

print(max2(5, 6))
print(max2(15, 9))
print(max2(99, 54))

print(type(max2))
```

#### 拯救內建函式
```python=
# 拯救函式
a = [1, 2, 3, 4, 5]

total = sum(a)

print(total)

b = [3, 4, 5, 6]
sum = 0
for n in b:
    sum += n

print('總和為:', sum)

print(type(sum))


del sum  # 把sum的功能刪掉(但不會刪掉python內建功能)
total = sum([1, 2, 3])  # 此行會恢復Python內建sum函式的功能
```

#### 練習
```python=
# 練習

# 1. 寫一函式, 名叫 check_score, 可以傳入一個整數參數, 如果數字大於等於60,  則回傳True, 如果小於60, 則回傳False

# 2. 將上一個函式改用lambda來實現

def compare_score(a1):
    if a1 >= 60:
        return True
    else:
        return False


a1 = int(input("請輸入分數:"))

if compare_score(a1) == True:
    print('及格')
else:
    print('不及格')


compare_score = lambda a2: True if a2 > 60 else False

a2 = int(input("請輸入分數:"))

if compare_score(a2):
    print('及格')
else:
    print('不及格')
```

## 例外(exception)
```python=
# 例外(exception)
# 當程式執行時發生預期外"邏輯錯誤"造成的執行失敗而產生的結果

try:
    a = int(input('請輸入一個整數:'))  # 當這裡產生例外，接下來同樣在try裡面的程式碼都會被忽略，並跳到except裡面執行
    print(f'你輸入了: {a}, 平方值: {a ** 2}')
    a /= 0
except ValueError:  # 捕捉ValueError例外
    print('您輸入了非整數的資料')
except ZeroDivisionError:  # 捕捉ZeroDivisionError例外
    print('發生除以0的例外')
except Exception as e:  # 將所有的例外都捕捉下來, 並將例外物件存到變數e裡面
    print('發生例外了:', e, type(e))
else:
    print('都沒有例外發生的時候會執行else裡面的程式碼')
finally:
    print('不管如何，都一定會被執行')

# 當產生例外時，錯誤訊息的最後一行， 冒號前面的描述即為該例外名稱; 冒號後面為該例外的描述
# 當例外產生時，如果沒有處理，結果就會是程式被中斷執行
```

#### 加上是否為數字的判斷
```python=
# 練習: 請幫猜數字遊戲加上輸入的資料是否為數的的判斷
guess_count = 0  # 紀錄猜了幾次

while True:
    player = input('請猜一個四位數的數字，數字不可重複:')
    guess_count += 1  # 次數加一

    # 檢查輸入是否為數字
    try:
        int(player)  # 嘗試轉型成int
    except ValueError:
        print('只能輸入整數數字')
        continue
    except Exception:
        print('輸入有問題, 請重新輸入')
        continue

    # 檢查是否為四個數字
    if len(player) != 4:
        print('數字只能四個，請重新輸入')
        continue

    # 檢查是否為四個不重複的數字
    if len(set(player)) < 4:
        print('數字不可重覆, 請重新輸入')
        continue
```

## 類別與物件
```python=
# 類別與物件
# 類別與函式一樣，定義好之後是不會被執行的
# 類別要執行之前，須要先產生物件才能被執行

# 類別內的函式(function)通常會改叫: 方法(method)
# 類別內的變數(variable)通常會改叫: 屬性(attribute)
class Car:
    def set_name(self, name):   # 類別內的函式第一個參數永遠都是self
        self.name = name        # self代表的是物件本身

    def show_name(self):        # 物件裡面的資料是物件內所有方法都可以共同使用的
        print(self.name)

    def add_gas(self, gas):
        self.gas = gas

    def show_color(self):
        print(f'車子是: {self.color}的')

c = Car() # 建立Car物件
c.set_name('BMW')
c.show_name()

c.color = '紅色'  # 將紅色存到color屬性內
c.show_color()

```

#### 類別的預設方法
```python=
class MyItem:
    def __init__(self, name, age, tall): # 建構式, 物件被建立時自動被呼叫, 不必自己呼叫, 通常用來初始化物件用
        self.name = name
        self.age = age
        self.tall = tall
        print('我被呼叫了')

    def show_info(self):
        print(f'我叫: {self.name}, 今年{self.age}, 身高{self.tall}公分')

    def __str__(self):  # 此方法在物件被當字串使用時會自動呼叫
        return f'我叫: {self.name}, 今年{self.age}, 身高{self.tall}公分'

m = MyItem('Aaron', 18, 180)  # 建立物件, 是個獨立的個體

n = MyItem('Andy', 20, 200)  # 建立物件, 與m物件沒有關係
# n.name = 'Andy'
# n.age = 20
# n.tall = 200

m.show_info()
n.show_info()

print(m)
print(n)
```

## 模組
#### my_module.py
```python=
def hello():
    print('hello')


class Hello:
    def show(self):
        print('Show hello')

hello_val = '你好'
```
#### main.py
```python=
# 模組
import my_module

my_module.hello()

m = my_module.Hello()
m.show()

print(my_module.hello_val)
```

#### 引入模組的其他方式
```python=
import my_module as m  # 在這個檔案內可以用m來呼叫my_module模組

m.hello()
print(m.hello_val)
```

```python=
# from my_module import hello      # 引入模組裡面指定的函式或變數或類別
# from my_module import hello_val
from my_module import *  # 將my_module裡面全部的功能都引入進來使用

hello()
print(hello_val)
h = Hello()
h.show()
```