前言
這是爬蟲教學的第二個系列,繼上次的搶購機器之後,這次我們要來學習如何做一個IG的抽獎神器!可能會有人想說,這個跟上次的搶購機器有什麼不一樣呢!這次要教大家在遇到需要不斷下滑的網頁時,要如何去爬取資料!那如果你是完全沒有基礎的人,建議你去看上一個系列的第一篇文章!裡面講解了關於爬蟲你應該要掌握的基礎知識!
關於IG或者FB爬蟲你應該要知道的事情!
其實這次原本是有做出一個網站要給大家使用看看的,下面是成果的圖片


但我實際把網站架設的Heroku之後,忽然功能就不能用了,我研究了兩三天之後才發現原來在上線之後,IG那邊會有反爬蟲程式來判斷你是不是使用爬蟲在登入他們的網站,如果是,他就會跳出一個網頁來鎖住你,所以如果有想要繼續研究相關內容的朋友
- FB和IG這種注重隱私的網站會利用亂碼持續更換他們的標籤屬性
- 他們會使用偵測爬蟲程式來阻止你爬蟲
- 他們的線上圖片資源有做cors的偵測
第三點簡單講解就是,如果你想要單純的像是使用imgur的圖片一樣去用他們的圖片是不行的,他會看你的網域是不是以facebook、instagram等等他們限制的網域開頭才能利用src去loading他們的圖片,雖然也有其他方式可以規避,但我查到比較多都要去使用php的付費server了,那不是我們教學的範圍。
看到這邊,你大概會了解,為什麼很多IG的抽獎機器會隨著時間而失去作用,上述兩點原因是最主要的,但我發現只要你還是使用本地的chromeDriver的話,基本上是不會被擋掉的,所以還是可以去學習網路上的IG抽獎程式是怎麼實作出來的!
前置作業
像上次一樣我們需要安裝的有
Python
- 官方網站連結 建議下載比較穩定的3.8或3.7版
Jupyter Notebook
- 在終端機裡面輸入 pip3 install Jupyter Notebook
Selenium
- 在終端裡面輸入 pip3 install selenium
Chromedriver
- 如果你是Windows的話請去官方下載對應你電腦版本的chrome ,並且將檔案放到和你即將寫的程式同一個目錄下,這樣才能運行喔
- 如果你是Mac的話,只需要通過homebrew輸入brew install chromedriver即可了,不過在這之前你需要先安裝Homebrew,需要了解Homebrew的話,可以去這篇文章看看
https://diary.taskinghouse.com/posts/4766365-homebrew-essential-mac-suite-management-tools/
程式碼講解
#chromeDriver
from selenium import webdriver #利用selenium做爬蟲
#做顯性等待
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
#抽獎功能
import random
首先這是我們這次會使用到的import,基本上都是為了顯性等待而使用的,在之前的教學就有提過顯性等待的用法,不過這篇會幫大家再複習一次!
設定好Chrome的路徑
#Mac版本(homebrew下載版本)
browser = webdriver.Chrome()
#Windows版本
driver_path = 'C:\Program Files\chromedriver.exe' #導入chrome driver才能開模擬器
browser = WebDriver.Chrome(driver.path)
在開始爬蟲之前我們必須要先設定好chrome的路徑,此處因為我是使用Mac安裝的方式,所以其實在安裝之後連path都不需要,直接導入就可以了,但如果你是windows版本的話,就必須要找到你下載對應版本的chromedirver放置的位置(最好是和要寫的程式放在同一個目錄下)之後就可以執行了,而成功後的畫面會長這樣。

登入Instagram
#----------------開始爬蟲 登入
web = 'https://www.instagram.com/accounts/login/'; #ig登入
browser.get(web)
ig_account_ele = WebDriverWait(browser, 20, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="loginForm"]/div/div[1]/div/label/input')))
print(ig_account_ele)
ig_account_ele.send_keys('你的帳號')#將使用者的資訊填入
ig_password_ele = WebDriverWait(browser, 20, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="loginForm"]/div/div[2]/div/label/input')))
print(ig_account_ele)
ig_password_ele.send_keys('你的密碼')#將使用者的資訊填入
login_ele = WebDriverWait(browser, 20, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="loginForm"]/div/div[3]/button/div')))
login_ele.click()
#確認登入狀態
WebDriverWait(browser, 20, 0.5).until(EC.presence_of_element_located((By.XPATH, '//*[@id="react-root"]//*[contains(@class,"_47KiJ")]')))
browser.get(post_URL)
第一次看到這邊的朋友可能會覺得怎麼那麼長一串,但不要擔心,我們一個一個慢慢看,這邊告訴大家,在使用selenium寫爬蟲時,重點就是將你在瀏覽這個網頁要做的事情的步驟轉換成程式碼而已,所以一般來說我們要抽獎的話,就是登入IG -> 找到貼文頁面 -> 開始瀏覽留言 -> 找到符合條件的留言 -> 抽獎 ,將所有你接下來要寫的爬蟲程式都一步一步拆分,那你就不會覺得爬蟲很難了!首先透過get()方法讓網頁跳轉到Instagram的頁面,接下來我們要輸入帳號密碼,而接下來要講解變數後的一大串程式碼,也就是顯性等待
顯性等待
我們首先要了解一件事情,你的程式碼運行的速度比你想像的快非常多,也就是說,假設你家的網路速度非常慢,很有可能整個程式碼跑完,你的網頁根本都還沒有載入完畢,而想像一下,如果我們在網頁還沒載入完畢時就執行了要尋找某個標籤元素的程式碼的話,會怎麼樣呢?
如果你對爬蟲有一點了解並且再此處使用find_element_by_id的話,很有可能會有時候出現Unable to locate element這個回報,而有時候卻不會,就是因為你等於在讓你的網路速度和你的程式碼賽跑,看誰跑得比較快,一但網路跑得慢了,程式碼就會找不到還未載入的標籤元素,就會出現這個回報,所以我們發明了顯性等待,在還沒有找到這個元素之前,我們請這行程式碼等一等,不要先偷跑,就是這個概念,是否很簡單呢?
WebDriverWait(browser(驅動器), 20(最多等待20秒), 0.5(每0.5秒搜尋一次))
.until((EC.presence_of_element_located((By.ID(搜尋方式), ‘login-passwd’(搜尋名稱))))
這是這個方法的具體變數,大家可以對照上面去寫喔!
了解這點之後,我們接下來就要去找到網頁內關於登入元素的標籤了,關於這點,建議你再次去觀看我爬蟲系列-搶購機器的第一篇文章喔。我們通過在chrome網頁中,右鍵我們要尋找的元素,右鍵點擊之後點擊檢查,正常來說這個步驟要重複執行兩次,因為第一次只是單純的叫出檢查介面而已,實際的畫面長這樣

而對著想要的元素右鍵點擊,會有個複製xpath的選項,我們便可以透過這個選項得到這個標籤元素的位置了,最後我們在對著登入的按鈕元素使用click()就可以完成登入了!但這邊我們還必須注意一點
確認登入狀態
按照順序的話接下來我們應該要直接去到貼文網站了,但如果你直接做的話,會發現接下來的步驟都找不到元素了,這就是在實作任何登入網站過後,跳轉頁面時,都要注意的小細節,必須要透過顯性等待某個元素來阻止跳轉太快的問題!原理和上述說明的是一樣的,不過由於沒有要尋找某個元素,所以我們可能會下意識忽略,於是我們再此處透過確認右上角登入頭像的標籤內容來知道我們真的有登入成功了!
到了此處我們就成功完成登入了,而這只是第一步以及幫各位建立一些基本知識而已,接下來關於滑動貼文和讀取貼文內容的部分,會有比較難的邏輯,於是我們在這邊做個分割點,有任何問題都可以在下方問喔!