---
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://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
}
```
程式碼也東常不會到很長,
除非你是要爬很大型的網站,
像是劍橋字典之類的,
如果想要爬的話也當然需要一點點偽裝,
不然很容易就會被踢掉,
最後需要注意一點的是要**適度**、**合法**
如果爬太超過的話不僅僅只是對網站的不尊重,
嚴重一點還有可能會**犯法**。