# Python爬蟲常識
###### tags: `python` `crawler`
## 幾種反爬蟲的方式
Google搜尋就是一種爬蟲,透過爬取網頁信息,來收集全世界網站的資料,其實也有很多公司或企業透過開發爬蟲來得到網際網路上的資訊,但其實被爬取的網站並不一定歡迎自己的網站內容被拿去使用,不論是內容有版權,或是因為爬蟲到到訪造成網站的流量增加影響到正常使用者的訪問,甚至無法訪問,因此會透過一些方式來阻擋爬蟲。
常見的反爬蟲方式有以下幾種:
#### 1、檢查user-agent
user-agent用來提供使用者的作業系統及版本、cpu類型、瀏覽器類型和版本,有了這些資訊,網站才會當成一個正常的請求,而非爬蟲。
#### 2. 檢查Referer
伺服器透過檢查Referer來了解該請求是從什麼地方來的,如果沒有該屬性,則直接擋住。
#### 3、透過IP來限制
當使用同一個ip多次頻繁的訪問網站時,伺服器會檢測到該請求可能是爬蟲操作,所以有可能在幾次正常的回應後發現次數太頻繁,因此就不回應了。
#### 4、設置請求間隔
有些惡意的爬蟲會從多個IP不間斷的攻擊網站,如果有這種情況,可以通過拉長請求時間間隔避免爬蟲短時間內大量的請求而影響到網站的正常運作。
#### 5、使用CAPTCHA
CAPTCHA 一字,是「全自動區分電腦和人類的公開圖靈測試」的縮寫。使用者常常會在網際網路上碰到 CAPTCHA 和 reCAPTCHA 測試,網站會在一些地方跳出CAPTCHA測試來讓使用者回答,因為題目並非固定的,所以如果是爬蟲遇到了就會造成失效。
#### 6、透過robots.txt來限制
robots.txt是一個限制爬蟲的規範,該文件是用來聲明哪些東西不能被爬取。如果網站根目錄存在該文件,爬蟲就要按照文件的內容來爬取指定的範圍。不過這個方式只限善意的爬蟲,如果是惡意爬蟲,並不會理會這個檔案。
> **補充:**
>
> robots.txt規格可以參考google開發文件:https://developers.google.com/search/docs/crawling-indexing/robots/intro?hl=zh-tw
## 降低被偵測
所謂道高一尺,魔高一丈,有反爬蟲的方式,自然也會有「反反」爬蟲的方式出現,以下是幾種在開發爬蟲時,用來降低爬蟲被偵測的方式:
- 設定使用者代理表頭(User-Agent)
- 設定參照位址表頭(Referer)
- 隨機切換IP位址
- 設定隨機的延遲時間
- 使用破解CAPTCHA工具
- 使用Selenium
- 避免蜜罐陷阱(Honeypot Traps)
#### 設定使用者代理(User-Agent)
使用者代理在HTTP的表頭裡面,設定後可以更像是真的瀏覽器發出的要求,不然就會被當成爬蟲來封鎖,user-agent用來告訴網站發出請求的使用者基本資訊。
![](https://i.imgur.com/9o6wHCJ.png)
vu
如下範例:
```python=
url = 'https://www.ptt.cc/bbs/Python/index.html'
headers = {'Accept':'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
'Upgrade-Insecure-Requests': '1',
'DNT': '1',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36'}
response = get(url, headers=headers)
html_doc = response.text
```
或是也可以使用Python模組`fake_useragent`來偽裝user-agent:
```
pip3 install fake_useragent
```
```
ua = UserAgent()
print(ua.google)
print(ua.safari)
print(ua.firefox)
print(ua.ie)
```
最厲害的是:
```
print(ua.random)
```
會根據真實世界的統計隨機產生一個 User-Agent 字串,這樣就能夠避免每一次請求(Request)都是相同的User-Agent而被偵測到。
> **補充:**
>
> 這個網站可以看你的瀏覽器user-agent設定: https://httpbin.org/anything
#### 設定參照位址(Referer)
請求表頭(Request Headers)中另一個重要欄位就是參照位址(Referer),用來告訴網站發出的請求(Request)是來自於哪一個網站,例如:
```
referer: http://www.aaronlife.com/
```
加入Referer欄位後,以上面來說,是用來告訴網站,這個請求來源為www.aaronlife.com網站。只是,如果在每一次的請求(Request)都使用相同的參照位址(Referer),在較嚴格的網站上,還是可能會被阻擋。
有一些反向代理的工具(例如:SEMRush),可以用來顯示目標網頁的反向連結,也可以來將不同的反向連結設定到referrer參數中,讓每一次的來源網站看起來都不相同,就可以降低被網站偵測到的風險。
#### 隨機切換IP位址
如果固定同一組IP位址,在固定的時間內大量的請求(Request)網站,很容易被偵測為網頁爬蟲而被封鎖。
所以再透過Python開發的爬蟲要執行任務之前,建議使用多組不同的IP下去隨機切換,以降低被偵測的風險,但一般個人用戶來說,很少人會同時有大量的IP,因此有一些網站服務可以幫忙做到這件事情,例如:
- Scrapingdog:https://www.scrapingdog.com/
有提供稱為ScraperAPI(https://www.scraperapi.com/,來讓Python可以取得多個IP來讓自己的爬蟲程式可以使用。
#### 設定隨機的延遲時間
網頁爬蟲最明顯的特性就是每一次的請求(Request)間隔時間都很有規律,也很有固定的模式,對於一般人類來說其實很難做到,所以,會很容易被偵測到。
所以,在每一次發出的請求(Request)之間,可以加入隨機的延遲時間(sleep),這樣就可以讓每一次發出的請求間隔都不一樣,也讓爬蟲的行為較為不固定:
```
import random
import time
delay_times = [5, 10, 16, 20, 32, 1, 43, 55] # 延遲的秒數
delay = random.choice(delay_choices) # 隨機選取秒數
time.sleep(delay) # 延遲,程式會停在這邊一段時間不執行
```
#### 使用破解CAPTCHA工具
雖然google的CAPTCHA問題都很難,甚至對人類來說,有時都還會答錯,對爬蟲就更不用說了;不過網路上仍可以找到一些服務針對google的CAPTCHA提供破解。
#### 使用Selenium
有些網站為了嚴格的偵測網頁爬蟲,除了檢查user-agent、請求間隔之外,甚至會瀏覽器的Cookie或是JavaScript的執行細節等等,因此還是很有可能會被偵測出這是一個爬蟲。
這時可以使用像Selenium的模組來開發爬蟲,和一般爬蟲不一樣的地方是,它是真實的會打開一個瀏覽器,並模擬人類在瀏覽器上的操作(透過程式來自動化操作),因此發出去的請求就跟一般瀏覽器沒有兩樣(甚至一樣),因為網站很難偵測出來。
一般使用這種方式開發出來的爬蟲又稱為動態爬蟲,因為會透過一些模擬人的動作來跟瀏覽器做一些互動。
#### 避免蜜罐陷阱(Honeypot Traps)
網頁蜜罐陷阱(Honeypot Traps)原理其實很簡單,就是許多網站會在HTML原始碼中埋入只有網頁爬蟲會讀取到的隱藏連結(例如帶有`display:none`或`visibility: hidden`樣式的連結),讓爬蟲爬到該連結後進入一個出不來的網址,然後一直無限循環的爬下去。
但因為人看不到這樣的連結,所以不會誤點而掉進去陷阱。
因此爬蟲在開發時需要注意要爬取的連結是否帶有這些屬性,或是透過參考該網站的「sitemap」來取得該網站所有的公開網頁再來進行爬取。
## 總結
在爬取的過程中,要尊重對方的網站及robots.txt,並需要注意智慧財產權的問題,並非所有爬到的資料都是可以拿來使用的,特別是拿來作為商業用途之前,一定要先知會對方,否則可能會衍生出法律問題。
---
## 結論
當一個有禮貌的好爬蟲。