---
# System prepended metadata

title: 爬蟲資料匯入Excel
tags: [工讀]

---

# 爬蟲資料匯入Excel 
###### tags: `工讀`

[toc]

:::info
### 目標
成功爬取 [此網站](https:[//](https://university-tw.ldkrsi.men/caac/)) 的以下資訊並匯入excel
1. 學校代碼
2. 學校名稱
3. 系所代號
4. 系所名稱
:::
遇到的困難
## 爬蟲
我一開始選擇用class爬學校，也成功了。但後來考慮到還要爬科系，所以改用tag爬。
而[這個網頁](https://university-tw.ldkrsi.men/caac/)基本上有**兩個select**，也就是**兩個選單**。

步驟 :

1. 用tag找出'select'  `driver.find_element(By.TAG_NAME ,'select')`
> 這邊find_element沒加s是因為此時需要的是第一個選單(各學校)，不會用到第二個選單(各系所)。而find_element只會抓第一筆，符合要求。

2. 每個option會有該校的value和inner html(也就是我們在網站上看到的文字)。所以接下來要用選項option抓全部學校的value，
    -  這邊**每所學校的option value不一定等於我們在網站上看到的該學校代碼(inner html)**。  
     > ex:校代碼是109的普大option value=109，而校代碼是109的科大option value=j109
     > 
我一開始以為學校的校代碼跟option value數字是一樣的，畢竟primary key有兩個很不合理。
後來才發現有些普大和科大的校代碼一樣，但他們的option value不可能一樣。(畢竟option value是獨一無二的)。

我原本以為他的value是連續的(ex:0~200)，這樣的話就很簡單，只需要一個一個加就好，殊不知到頭來需要去抓一堆option value。這邊花了很多時間，這部分設計的很奇怪。

3. 該怎麼抓所有value? (這邊的value不是指校代碼喔，校代碼只是inner html)
   - 把所有option找出來(裡面會有各校value、校代碼、校名)
    `search_input = driver.find_elements(By.XPATH, "//option")`
    
   -  把選單內該一個學校option 抓下來`.get_attribute("value")`
   
4. 知道所有學校的value後，就可以用value來抓系的資料
   - 用Select(點選的功能)  點選第一個選單(有全部校名的那個選單)
   `search_input = Select(driver.find_element(By.CSS_SELECTOR, "select"))`
   (這個套件提供的點選功能很讚) 
     > 還有查到select_by_visible_text(應該是指inner html)等功能。
     
   - 用value去模擬人依序點選選單內的學校(照option value依序由上往下點選)              `.select_by_value(value)` 
   
   - 接著要點選第二個選單去抓系，要考慮到在選單點選不同學校後，科系也會跟著改變(不同學校有的科系不同)。
   
   - find_elements會抓到兩個選單，我們這邊要使用得是第二個選單(有該校所有科系)。
    `search_input = driver.find_elements(By.XPATH, "//select")  `
     >  search_input  現在有{所有學校}和{該校對應的所有科系}這兩個選單。
   
   - 用.text抓到第二個選單所有option的inner html(系代碼和系名)，再用for迴圈把該校的全部科系資料放進final這個list
   `final=search_input[1].text.split("\n")` 
     
    
## 匯入資料到excel
1. 創一個字典叫做dict，再添加資料進去 {key=各學校代碼+校名，value=該校各系代碼+系名}
 `dict[total_school_name[index]] = final `
 
2. 輸入第一列標題
```python=
s1.cell(1,1).value="學校代碼"
s1.cell(1,2).value="學校名稱"
s1.cell(1,3).value="校系代碼"
s1.cell(1,4).value="校系名稱"
```
3. 然後依序把資料匯入
```python=
school_num=1 #算到第幾所學校
row=2 #一開始要從第二列開始寫，之後再往下寫
for key, value in dict.items(): #各學校詳細資料 (key)       
    for i in value: #該校所有科系資料(value)
        s1.cell(row,1).value=(total_school_name[school_num])[1:4]
        s1.cell(row,2).value=(total_school_name[school_num])[6:]
        s1.cell(row,3).value=i[1:7] #寫入系代碼
        s1.cell(row,4).value=i[9:] #寫入校名
        row+=1
    school_num+=1    
```
---
## 學習到的功能
> 因為我從來沒學過css和js，也完全沒碰過網頁，所以花很久時間在查資料，查了幾天沒進展的話就會跟同學求助。
> 下面是一些這次學習過程中，我覺得蠻好用的技巧，想紀錄下來。

- F12 -> 主控台 -> 輸入 `document.getElementsByTagName.('要搜尋的tag')` -> 
![](https://i.imgur.com/0RQjspl.png)

- [0]代表第一個選單(index[0])
![](https://i.imgur.com/0KszqAH.png)

- `document.getElementsByTagName('select')[0][1]`的[1]代表選單的第2項(因為其index[1])
 ![](https://i.imgur.com/Hn1d57V.png)
 
 ---
 ### Excel文件在openpyxl的名詞代號

- `workbook`（活頁簿）：也就是一個excel檔案
- `worksheet`（工作表）：一個excel可以有很多個工作表，目前正在觀看或處理的工作表又稱作「活動中的工作表（active sheet）」
- 欄（column）：工作表中的直欄，以A、B、C…代表
- 行（row）：工作表中的橫列，以1、2、3…代表
- 儲存格（cell）：工作表中的每一個都是一個資料儲存格，每一格稱為`cell（row, col）`。

### 建立Excel檔案
- 前置寫入
```python=
import openpyxl
import os
```
- 切換到電腦指定路徑
```python=
os.chdir(r"C:\Users\annnn\crawler")  # os.chdir 是 python
``` 
> 要記得程式正在操作的檔案是我們填入路徑下的那個檔案，儘管excel檔案名稱一樣，在不同路徑下開啟會看起來有所不同。

**簡單來說就是，要從對的路徑開excel檔案，才能看到剛才編輯的結果。**


- 建立新Excel檔案(Workbook)
```python=
 wb = openpyxl.Workbook()
```
- 開啟舊Excel檔案
```python=
wb = openpyxl.load_workbook('test1.xlsx') 
```
- 儲存檔案 `wb.save('test1.xlsx')` 

> 以上指令做完後，達成在指定路徑下(C:\Users\annnn\crawler)存了新檔案('test1.xlsx')


### 操作Excel工作表
> - 開啟 Excel 活頁簿後，可以使用 active 屬性取得目前使用的工作表 ( 開啟 Excel 活頁簿時第一個顯示的工作表 )
> - 使用字典取值的方法讀取指定名稱的工作表
---


可以加強的: 下關鍵字的能力/把小功能分開練習
