Selenium

Selenium

需要在 Python 上操作瀏覽器的話,我會選擇使用 Selenium; 以爬蟲來說,和 requests 不同的地方在於, 像是在讀取網頁時,使用 Selenium 開啟瀏覽器的話可以幫我們處理掉渲染的問題。 這篇主要會以 Selenium 的方式來取得痞客邦的 Access Token。

先搞懂痞客邦的流程

首先,我們先到痞客邦的開發者網頁

PIXNET
PIXNET
或是可以直接到 API Explorer 的畫面
API Explorer
API Explorer
接下來會需要進行登入的動作
Login
Login
登入成功後,便是授權給 API Explorer 權限來取得 Access token
Granted
Granted
最後可以在 API Explorer 的畫面上看到 Access Token。
AccessToken
AccessToken

程式方面

我們會使用到 Selenium 的這些元件

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
from selenium.common.exceptions import NoSuchElementException
from selenium.common.exceptions import TimeoutException
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
def get_token():
    url = 'https://devtool.pixnet.pro/#/'
    # 使用 Firefox 來開啟網頁
    driver = webdriver.Firefox()
    # 打開 API Explorer 的畫面
    driver.get(url)
    # 進行登入
    driver.get('https://panel.pixnet.cc/login/openid?done=https%3A%2F%2Fdevtool.pixnet.pro&openid=https%3A%2F%2Fmember.pixnet.cc%2Flogin&easy_login=1')
    # 選擇臉書登入
    driver.get('https://panel.pixnet.cc/login/facebooklogin?done=https%3A%2F%2Fdevtool.pixnet.pro&easy_login=1&register_url=%2F%2Fmember.pixnet.cc%2Fregister')
    # 在 Email 和 Password 欄位填上值,並按下登入按鈕
    email = driver.find_element_by_id('email_container')
    password = driver.find_element_by_id('pass')
    login_button = driver.find_element_by_id('loginbutton')
    email.send_keys('Your Facebook email')
    password.send_keys('Your Facebook password')
    login_button.click()
    # 跳轉至授權畫面並按下同意
    driver.get('https://emma.pixnet.cc/oauth2/authorize?redirect_uri=https://devtool.pixnet.pro/index/cb&client_id='Your client id'&response_type=code')
    driver.find_element_by_id('send-Allow').click()
    time.sleep(5)
    # 使用 WebDriverWait 來等候標題出現 EMMA API Explorer(這邊我只寫 EMMA)
    try:
        WebDriverWait(driver, 10).until(EC.title_contains('EMMA'))
    except TimeoutException:
        print('time out')
    finally:
        # 接著 Parse 出 Access token 並且 return。
        soup = BeautifulSoup(driver.page_source, 'html.parser')
        ps = soup.find_all('p', 'form-control-static ng-binding')
        token = ps[0].string.replace(' ', '').replace('n', '')
        driver.close()
        return token

可能遇到的問題

geckodriver

由於我是使用 Ubuntu + Firefox 來執行,而在 Firefox 後續的版本中, 並沒有內建 geckodriver,需要手動安裝到電腦之中。

Crontab

若你是使用 Crontab 來跑的話,由於 Crontab 本身並不會有 output 的輸出, 意思是指跑 Crontab 時,也不會自己跳出 Firefox 的畫面; 會導致 Selenium 發生錯誤。 解決的方式是使用 pyvirtualdisplay 來弄一個虛擬的畫面, 給 Firefox 作為使用。 上面的程式碼則補上:

...
from pyvirtualdisplay import Display
def get_token():
    # 先準備好虛擬的畫面
    display = Display(visible=0, size=(800, 600))
    display.start()
    ...
    # 最後記得關掉畫面
    display.stop()
    return token

大致上是這樣,就可以利用 Selenium 的方式取得痞客邦的 Access Token!

Licensed under CC BY-NC-SA 4.0
comments powered by Disqus