---
# System prepended metadata

title: 爬蟲
tags: [Code]

---

---
tags: Code
---
# 爬蟲

## 標頭檔

```python=
import requests as req
from bs4 import BeautifulSoup
```

## 憑證 ( 先忽略)
```python=
ssl._create_default_https_context =ssl._create_unverified_context
```
## 讀取網頁

<!--
### 提供資料
為了可以讓網站正確識別且認定你不是機器人，你需要提供資料
<!--
```python=
qi
request = req.Request(url,  headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.55 Safari/537.36 Edg/96.0.1054.43",
        "Cookie" : cookie
})

```


```python=
request = req.get()
```
-->



## 讀取網頁
```python=
data = req.get(url)
```


# 搜尋

## 編碼
首先需要用`BeautifulSoup`來重新編碼
```python=
root = BeautifulSoup(data, 編碼格式)
```

編碼格式有很多種，則一即可
![](https://i.imgur.com/GWwpFkp.png)
(https://www.jianshu.com/p/424e037c5dd8)


## 搜尋
搜尋基本上有兩種
1. $find()$
2. $find\_all()$

```python=
first = root.find('div', class_ = "")
for search in root.find_all('div', class_ = "")
    ...
```

## 上課(3/8)

```python=
import requests as req
from bs4 import BeautifulSoup

data = req.get("https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid=a001")
#print(data.text)

root = BeautifulSoup( data.text, 'html.parser')
#print(root)
#<div class="container">
root = root.find('div', class_="container");

#<div class="panel panel-default">
ProblemData = root.find_all( 'div', class_ = "panel panel-default") #[ ..., ..., ...., ...]
print(ProblemData, len(ProblemData))

# string.replace(舊, 新)
# " ","\n"(換行), "\t"(tab鍵) 

for PerdataId in range(len(ProblemData)) :
    ProblemData[ PerdataId ] = ProblemData[ PerdataId ].text #轉成字串
for Perdata in ProblemData :
    Perdata = Perdata.replace(" ", "")
    Perdata = Perdata.replace("\n", "")
    Perdata = Perdata.replace("\t", "")
    Perdata = Perdata.replace("\r", "")
    print(Perdata)
```

## 整體(如果熟練使用)
```python=
import requests as req
from bs4 import BeautifulSoup 
import json
import os

def WriteData( DataForWrite:str, file ) :
    #這個函式可以把字串寫到檔案裏面
    with open( file, 'w', encoding="utf-8") as f:
        f.write( DataForWrite )

def ReplaceStrings(Strings:str, Replace:list[str], ReplaceTo:str) -> str :
    # Strings: str, 其中 :str是指定他的型態，譬如此處是限定只能傳入字串
    # def () -> str 則是限定他return的型態
    # 可以在弱型別的python中確認型態，減少出錯的機會
    for i in Replace:
        Strings = Strings.replace( i, ReplaceTo )
    #此處和上面挺像，只是把操作都壓縮到for迴圈
    return Strings

def ReplaceString(String:str, Replace:str, ReplaceTo:str) -> str:
    #這裡是單個replace，可以當作小小的參考?本質上沒什麼用處，可以更好的了解函式
    return String.replace( Replace, ReplaceTo )

def GetProblemData(ProblemID:str, Tofile: str) -> None: 
    """ 3/8 3~10行 """
    data = req.get( f"https://dandanjudge.fdhs.tyc.edu.tw/ShowProblem?problemid={ProblemID}") #f 是可以讓你在字串裡面有變數 {}
    webData = BeautifulSoup( data.text, "html.parser" ) 
    #panel panel-default 可以發現這是他們都共有的特點
    webData = webData.find( "body" ) .find( "div", class_ = "container")
    
    
    """ 3/8 12~20行 """
    webData = [ i.text for i in webData.find_all( "div", class_ = "panel panel-default" ) ]
     #這一行的作用等價於上課時所提到的 12~20行，不會的話也沒有關係，只是想展現一下如果熟練使用之後可以縮短程式碼
    
    """ 3/8 21~26行 """
    #print(ReplaceStrings("h\t\te\n\n" , ["\t", "\n"], "" ))
    for i in range( len( webData ) ):
        webData[ i ] = ReplaceStrings( webData[ i ], [ "\n", "\r", "\t", " " ], "") 
        #print(webData[ i ])
    """ 3/8 未教"""
    if len(webData) == 0: 
        print("No Data")
        return 
    
    # if To file not exist, create it(如果檔案不存在，則新建一個)
    if not os.path.exists( Tofile ): #判斷資料夾是否存在
        os.mkdir( Tofile ) #創立一個新資料夾
        
        
    WriteData( json.dumps( webData, indent = 4, ensure_ascii = False ), file=f"{Tofile}/{ProblemID}.json" ) 
    #json.dumps 是可以把list, dict等轉換成字串的形式
    #而WriteData 則是出現在上面的函式，可以把字串寫到檔案裏面
    #這邊也有用到f"{}"，是來生成檔案存放名稱的
    
if __name__ == "__main__":
    import time
    for i in range( 1, 10 ):
        time.sleep( 0.05 )        
        print( f"Get Problem a{i:03}") 
        GetProblemData( f"a{i:03}", "Data")
        
```

# 結論
其實這樣就基本上把爬蟲學完了，
爬蟲其實蠻制式化的?
基本流程大概如下

```graphviz
digraph {
    st[label="觀察網頁 "]
    sub1[label="找出共通點"] 
    sub2[label="獲取原始碼"]
    sub3[label="解構原始碼獲\n取所需要的資訊"] 
    sub4[label="將資訊整理(美觀)"]
    end[label="存取下來"]
    st -> sub1
    sub1 -> sub2
    sub2 -> sub3
    sub3 -> sub4
    sub4 -> end
}
```

程式碼也東常不會到很長，
除非你是要爬很大型的網站，
像是劍橋字典之類的，
如果想要爬的話也當然需要一點點偽裝，
不然很容易就會被踢掉，
最後需要注意一點的是要**適度**、**合法**

如果爬太超過的話不僅僅只是對網站的不尊重，
嚴重一點還有可能會**犯法**。
