---
# System prepended metadata

title: Python教學
tags: [研究]

---

# Part 1

## 安裝

### [Python官方連結](https://www.python.org/)
* 點選 download 下載最新版本，目前是3.11.5版，下載完畢後直接安裝。
![python.org](https://hackmd.io/_uploads/H1x8EJCRn.png)

### [Anaconda官方連結](https://www.anaconda.com/download)
* 點選 Windows 版本下載，一樣下載完畢後直接安裝。
[安裝參考1](https://simplelearn.tw/anaconda-3-intro-and-installation-guide/)
[安裝參考2](https://medium.com/python4u/anaconda%E4%BB%8B%E7%B4%B9%E5%8F%8A%E5%AE%89%E8%A3%9D%E6%95%99%E5%AD%B8-f7dae6454ab6)
![](https://hackmd.io/_uploads/HyU8HJR0n.png)

### 安裝後確認
* 開啟 cmd，輸入下方指令(小寫v)，可進入 python "測試功能模式"。
* 若要結束此模式，可輸入 Ctrl+Z 即可跳回原來的模式。
```python=
python -v
```

* 開啟 cmd，輸入下方指令(大寫V)，可查看安裝版本。
```python=
python -V
```
![](https://hackmd.io/_uploads/H18wv1RC2.png)

:::success
:bulb: **安裝完成後，先進入 python "測試功能模式"吧。**
:::

## 變數
* 變數命名可以包含以下字元
    * 小寫字母
    * 大寫字母
    * 數字
    * 底線 _

* 可以是
    * aName
    * Name1
    * Name_of_division___DigiTech
    * _HowManyGroup
    * _2HappyTeam

```python=
aName = "Justin"
Name_of_division___DigiTech = "數位科技"
_HowManyGroup = 3.5
```

* 不可以是
    * 3
    * 3a
    * 5_
    * groupfunction!
    * another-name
```python=
3 = "賈斯汀" #錯誤的變數命名
groupfunction! = "no idea"
```    

## 基本型別
* 檢測變數型別的方法
```python=
var=0
type(var)
```
### 布林
* True, False
* 對或錯
* 相等或不相等
* 黑或白
```python=
Sleep_In_Class = False
Sleep_At_Home = True
```

#### 運算
```python=
# 運算邏輯是否相等
Sleep_In_Class == Sleep_At_Home # 運算結果是False

# 運算邏輯是否不相等
Sleep_In_Class != Sleep_At_Home # 運算結果是True

# 比較數字大小
x = 5
y = 7

#大於
x > y # 運算結果是False

#小於
x < y # 運算結果是True

#大於等於 >=
#小於等於 <=
```

### 數字

#### int
```python=
var = var + 1 #var += 1 也是一樣
print(var)
```

#### float
```python=
var = 9.9
print(var)
```

#### 數字運算
|運算子|說明|範例|結果|
|--|--|--|--|
| + | 加法 | 3 + 5 | 8 | 
| - | 減法 | 3 - 5 | -2 | 
| * | 乘法 | 3 * 5 | 15 | 
| / | 除法 | 3 / 5 | 0.6 |
| // | 除法捨去 | 3 // 5 | 0 |
| % | 餘數 | 3 % 5 | 3 |
| ** | 次方 | 3 / 5 | 243 | 

### 字串

* 如何建立
```python=
# 使用單引號
aString = '一串文字'
# 使用雙引號
aString = "一串文字"
# 單純建立一段文字
str(一串文字)
```

* 連接文字，使用"+"號
```python=
Constarin1 = "控制01-1"
Constrain2 = "控制02-1"
# 連接所有字串，結果應該是 控制01-1, 控制02-1
Full_String = Constarin1 + ", " + Constarin2
```

#### 字串處理
* 使用中括號 **[ ]** 取得字元
以 "控制12-3" 為例，字串中有6個字元，下方則代表各個字元在字串中的位置。

| pose 0 | pose 1 | pose 2 | pose 3 | pose 4 | pose 5 |
| - | - | - | - | - | - |
| 控     | 制     | 1     | 2     | -     | 3     |

* 取得特定位置
```python=
Constarin1 = "控制12-3"
#取得字串位置2的字元
Constarin1[2] # 顯示1
```

> **公式：string[ 起點位置 : 終點位置 : 間隔]**

* 指定起始終點並取得一段文字
```python=
Constarin1 = "控制12-3"
#指定起始終點
Constarin1[1:4] # 顯示"制12-"
```

* 反轉字串
```python=
Constarin1 = "控制12-3"
#step倒序(-1)
Constarin1[::-1] # 顯示"3-21制控"
```

* 其他有用函式
```python=
#算長度
#用途：透過此函數計算內容長度，符合長度的內容才可以寫入資料庫
Constarin1 = "控制12-3"
len(Constarin1) # 6

#分段
#用途：透過特並符號將一大串文字分段，分段後就可以拿來做其他操作
NameString = "Mike, Julian, Lucky, Cathy"
NameString.split(',') # ['Mike', 'Julian', 'Lucky', 'Cathy']

#join 結合
NameSplitString = ['Mike', 'Julian', 'Lucky', 'Cathy']
NameString = ','.join(NameSplitString) # 'Mike,Julian,Lucky,Cathy'

#replace 替換
#用途：替換字串中的符合條件的文字
aStr = "a duck goes to rock"
aStr.replace('duck', 'lion') # 'a lion goes to rock'

#strip 剝除
#用途：移除字串前後的空白格
aSpaceStr = " haha  " #前後有空格，比對關鍵字的時候會有問題，因為" haha  "不等於"haha"
aSpaceStr.strip() # 移除前後空白後，結果為"haha"

# in 是否在裡面
# 用途：檢查關鍵字是否存在
CaseStr = '''經查辦理聯徵中心信用資訊查詢作業，雖已取得
客戶之聯徵查詢同意書(LNC-356)，經查客戶僅向本行申請
房屋貸款、信用貸款，其同意書應僅得勾選第一項「一般授信」、
第六項、「介接查詢」。
'''
key = "同意書"
key in str # 檢查後結果為 True
```

#### 格式
```python=
thing = 'duck'
place = 'lake'
'The {} is in the {}!'.format(thing, place)
# 顯示為 The duck is in the lake!

#也可以寫成
"The " + thing + "is in the " + place
```
:::success
:bulb: **下面要開始真正來寫程式了，先來安裝vscode**
:::

## [vscode下載](https://code.visualstudio.com/)
* 點選畫面上 Download for Windows 下載最新版本，下載完畢後直接安裝。

## 容器
|資料型態|可接受多資料型態|順序|改變內容|內容重複|
|--|--|--|--|--|
| list | V | 有 | 可 | 可 |
| tuple | V | 有| 不可 | 可 |
| set | V | 無 | 可 | 不可 |
| dict | V | 有 | 可 | key值不可重複 |

### 容器表頭名詞解釋
* **可接受多資料型態**
    * 意思是容器內放入任何型態的資料都是可以的，例如說list可以先放字串進去後，再放數字進去。其他高階語言不一定能支援這樣的功能，如C#的list裡，放置的都必須是同一種型態，若要放字串，就都只能放置字串。
* **順序代表**
    * 這個容器是可以支援排序，通常是呼叫.sort()方法來達到。(可參考下方list其他操作)
* **改變內容**
    * 意思是指容器的東西放進去之後，無法透過set的方式設定新的值，若透過其他的方法也許可以做到。
* **內容不可以重複**
    * 代表每次方進去的東西是不能相同的，例如dict就不能放進去兩個相同的key值，有點類似資料庫的primary key的概念，表內是無法存在兩個相同的key在同一個欄位。

### list
* list的建立是使用[]
```python=
i = ['amos', "taipei", 44] #list裡面可以放置不同的資料型態
print(i) #i是一個list，把i列印出來在畫面上面看看是什麼？

print(i[2]) #透過[]取得i裡面的值，然後再列印出來會得到 44

i[1] =  '台北'
print(i)  # ['amos', "台北", 44]
```
* list其他操作
```python=
i = [1, 100, 10, 5]
print(i[1])

i.append(0.2) # 追加資料
print(i)

i.insert(2, 50) # 從第2筆插入50
print(i) # ???

i.remove(1) # 移除list內第一個符合該內容的資料！
print(i)

i.index(1) # 取得1在list中的索引值（第幾位）
print(i)

i.pop(i) # 取出，採先進後出法
print(i)

i.sort() # 由小到大排序
print(i)

i.reverse() # 由大到小排序
print(i)


print( len(i) ) # 求list筆數

print( max(i) ) # 求list中最大值

print( min(i) ) # 求list中最小值

print( sum(i) ) # 將總list內的數值


i.clear() # 清除全部內容
print(i)
```
### tuple
* tuple的建立是使用()與逗號","
```python=
i = (1, "taipei", 2)
print(i)
```
### set
```python=
i = {1, "taipei", 5}
print(i)
print("taipei" in i)  # True
i.add("高雄")
print(i)  # {1, 'taipei', 5, '高雄'}
```
### dict
```python=
j = {
    "id": "A1122", 
    "name": "Amos Tsai", 
    "year": 5
}

j["id"] = "AAAA"
print(j["id"]) #"AAAA"

member = {
    "number": "1020501",
    "name": "小傑",
    "age": 32,
    "sex": "M",
    "interest": [
        "網頁設計",
        "撰寫文章"
    ]
}

member['interest']  # ["網頁設計", "撰寫文章"]
member['interest'][0]  # 網頁設計
```
```python=
school = [
    { "id": "A1122", "name": "Amos Tsai", "year": 5 },
    { "id": "A1123", "name": "frank", "year": 3}
]
a = ["amos", "frank"]
print(school[1]['name']) #frank
```


```python=
school = { "id": "A1122", "name": "Amos Tsai", "year": 5 }
school = list(school.values())
print(school) #['A1122', 'Amos Tsai', 5]
print(type(school)) #<class 'list'>

a = [123, 555, "abc"]

print(a) #[123, 555, 'abc']
print(type(a)) #<class 'list'>
a = tuple(a) #沒東西

print(a) #(123, 555, 'abc')
print(type(a)) #<class 'tuple'>
```
### 大型容器
> Only an example
```python=
#大型資料集
BigContent = {
    "1":
    "Function": [
        "網頁設計",
        "資料庫串接"
    ],
    "2":
    "Function": [
        "專案管理",
        "文件撰寫"
    ]
    "3":
    "Function": [
        "法規制定",
        "行政流程"
    ],
    ...
}
```
}

## 程式結構 (流程控制)

### if
```python=
sleep = True
if sleep: # 末端為分號 :
    print("End class !")
```

### if, elif, else
```python=
iphone15 = "Blue"
if iphone15 == "Blue":
    print("Buy for myself")
elif  iphone15 == "Pink":
    print("Buy for mom")
else
    print("Don't buy")
```
### while
```python=
count = 1
while count <= 5
    print(count)
    count += 1

#以下為顯示結果
1
2
3
4
5
```

### break
```python=
count = 1
while count <= 5
    print(count)
    
    # >= 3的時候強制跳離，下面就不執行+1的動作了，直接結束 while 迴圈
    if count >= 3
        break
        
    count += 1

#以下為顯示結果
1
2
3

#程式結束
```

### continue
```python=
count = 1
while count <= 5
    print(count)
    
    # >= 3的時候會跳過下方+1的動作
    if count >= 3
        continue
    
    # count一直無法+1，此while會造成無窮迴圈，成是會一直卡在這邊無法繼續往下執行
    count += 1

#以下為顯示結果
1
2
3

#但是python程式會一直執行，無法結束。
```

### for 與 in 迭代
* 在特定範圍內迭代內容，自己覺得使用 for 比較安全
```python=
word = "hello!"

for letter in word
    print(letter)
    
# 結果
h
e
l
l
o
!

# while 也一樣可以達到同樣的效果
offset = 0 #給定位置指標
while offest < len(word)
    print(word[offset])
    offset += 1

```

# P.99

## 函式 Function

## 模組

## 物件

## 套件


# Part 2

## 爬蟲套件介紹

## 爬蟲許願池

## 來寫爬蟲
* 商工登記公示資料查詢服務網站查詢王永慶的爬蟲範例
```python=
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By

import time
import random

#商工登記公示資料查詢服務
url = 'https://findbiz.nat.gov.tw/fts/query/QueryBar/queryInit.do'

#查詢人名
SearchName = '王永慶'
#SearchName = '張忠謀'

# list轉換Dictionary - 目前沒用到
def convert2Dict(lst):
   res_dict = {}
   for i in range(0, len(lst), 3): #3個為一組
       res_dict[lst[i]] = lst[i + 1]
   return res_dict

# 裝睡
def PretentSleep(s, e):
    r = random.randint(s, e)
    print('裝睡' + r.__str__() + '秒')
    browser.implicitly_wait(r)


# 以下為 main 開始
browser = webdriver.Chrome()

#開網頁
browser.get(url)

print('網頁內容')
print(browser.page_source)

#找到輸入框
QueryName = browser.find_element(By.NAME, 'qryCond')
QueryName.send_keys(SearchName)

#找到radio的按鈕
QueryType = browser.find_element(By.ID, 'infoName')
QueryType.click()

#為了不要讓網站發現爬蟲
PretentSleep(1, 3)

#找到查詢按鈕
queryBtn = browser.find_element(By.ID, 'qryBtn')
queryBtn.click()

#等待 wait 為了不要讓網站發現爬蟲
PretentSleep(3, 5)

# #切換為表格型式
# viewType = browser.find_element(By.ID, 'viewTable')
# viewType.click()

TotDataRowCount=0
currentPage=1
maxPage=1

try:
    #找到總頁數
    TotDataRowCount = browser.find_element(By.NAME, 'pagingModel.totalCount').get_attribute('value')
    print('資料總筆數 : ' + TotDataRowCount)
    currentPage = browser.find_element(By.NAME, 'pagingModel.currentPage').get_attribute('value')
    print('目前分頁 : ' + currentPage)
    maxPage = browser.find_element(By.NAME, 'pagingModel.totalPage').get_attribute('value')
    print('最大分頁 : ' + maxPage)
except:
    print("沒有其他分頁")


#設計分頁點選


#抓取公司資訊
CompanyInfos = browser.find_element(By.ID, 'vParagraph')
print(type(CompanyInfos))

splitinfo = CompanyInfos.text.split('\n') # it is a list

res_dict = {}
for i in range(0, len(splitinfo), 3):

    #這邊僅用逗號區隔資料為list，後面要固定欄位index去抓取固定的值
    detailInfo = splitinfo[i+1].split(',')
    for k in range(0, len(detailInfo)):
        detailInfo[k] = detailInfo[k].replace(' ', '')                          

    #加入到 dictionary 裡面，這邊就是完整爬取的資料了
    res_dict[splitinfo[i]] = detailInfo


#彙整不同頁數的資料集

browser.quit()


#資料集寫入當地 csv 檔
```


## 請 ChatGPT 幫忙寫 Python
### Prompt
* 請寫一段python function，function要可以讀取一個Excel檔案，這個Excel檔案內共有兩個頁籤都需要被讀取，第一個頁籤內容有5個欄位與10個列，第二個頁籤內容有2個欄位與20個列，分別讀取後，將讀取後的內容放在不同的 Dictionary 中並回傳。
### ChatGPT 的回答
* 先安裝套件
![安裝套件](https://hackmd.io/_uploads/SJ-vHgdWp.png)

* 開始幫你寫 python 程式
![寫程式](https://hackmd.io/_uploads/HyAdHedWT.png)

* ChatGPT實際產出的程式碼
```python=
import pandas as pd

def read_excel_to_dict(file_path):
    # 創建兩個字典，用於存放兩個頁籤的內容
    sheet1_data = {}
    sheet2_data = {}

    # 讀取 Excel 檔案
    xls = pd.ExcelFile(file_path)

    # 讀取第一個頁籤的內容
    # 頁籤名稱要與檔案內容相同
    sheet1_df = pd.read_excel(xls, sheet_name='第一個頁籤')

    # 將第一個頁籤的內容轉換為字典
    for column in sheet1_df.columns:
        sheet1_data[column] = sheet1_df[column].tolist()

    # 讀取第二個頁籤的內容
    # 頁籤名稱要與檔案內容相同
    sheet2_df = pd.read_excel(xls, sheet_name='第二個頁籤')

    # 將第二個頁籤的內容轉換為字典
    for column in sheet2_df.columns:
        sheet2_data[column] = sheet2_df[column].tolist()

    # 回傳兩個字典
    return {'第一個頁籤': sheet1_data, '第二個頁籤': sheet2_data}

# 使用示例
file_path = '你的Excel檔案.xlsx' #這邊要改成自己的檔案路徑
result = read_excel_to_dict(file_path)
print(result)

```

* 執行結果
![執行結果](https://hackmd.io/_uploads/HyBKnluba.png)
