python
selenium
crawler
動態網頁顧名思義,指的就是網頁內容是動態的,每次瀏覽同一個網頁的內容可能都不同,例如: 書本的搜尋,匯率,新聞等等,根據使用者的選擇或輸入不同的互動,動態的產生網頁內容。
產生有兩種方式:
在網頁伺服器內以伺服器程式語言(如: PHP,ASP.NET或JSP等等)執行後來動態產生網頁後再回應給客戶端。
對於爬蟲來說,如果爬取動態網頁內容,只會得到一堆JavaScript程式碼,因為網頁內容需要透過執行JavaScript程式碼後產生,所以對於動態網頁,爬蟲會看不到執行後的結果,所以無法使用Beautiful Soup或lxml來爬取資料。
Selenim為一個跨平台的自動瀏覽器(Automates Browsers),其原本是用來做為Web應用程式的軟體測試框架,本身為開放原始碼,用在爬蟲上,可以做為模擬使用者輸入內容,點擊連結來與網頁作互動。
Selenium為數個元件組合而成的一個套件,其元件有:
對Python來說,需要安裝有個,一個是Selenium Client API(也就是Python模組),另一個就是WebDriver,。
pip3 install selenium
https://www.selenium.dev/documentation/webdriver/getting_started/install_drivers/
備註:
- Selenium 4.6版(包含)以後不需要再下載driver了。
- Selenium 4.5版以前請下載對應瀏覽器的WebDriver
注意:
- WebDriver並非下載最新版本就好,而是下載的版本必須和你的瀏覽器版本一樣,例如你的Chrome瀏覽器是106版,那WebDriver就要下載106版的。
Windows作業系統請下載chromedriver_win32.zip即可。
將下載的zip檔案解壓縮到你的Python程式目錄下。
引入selenium的webdriver物件
from selenium import webdriver
初始化WebDriver
driver = webdriver.Chrome('chromedriver')
注意:
如果是在MacOS下,如果和Python放在同一層目錄,需要額外加上代表目前路徑的
./
符號,如:driver = webdriver.Chrome('./chromedriver')
設定等待網頁載入的時間,如果提早載入完成,會提早結束等待,如果時間不夠,讀到的網頁內容會有殘缺:
driver.implicitly_wait(10)
連線到網站:
driver.get('https://rate.bot.com.tw/xrt?Lang=zh-TW')
印出網頁標題:
print(driver.title)
取得網頁內容並印出:
html = driver.page_source
print(html)
也可以利用BeautifulSoup來分析網頁內容:
soup = BeautifulSoup(driver.page_source, 'lxml')
print(soup.prettify())
將取得的網頁內容存到本地端:
with open('index.html', 'w', encoding='utf-8',) as file:
file.write(soup.prettify())
關閉WebDriver, 瀏覽器也會跟著關閉:
driver.quit()
from selenium import webdriver
from bs4 import BeautifulSoup
import requests
driver = webdriver.Chrome('chromedriver')
driver.implicitly_wait(10)
driver.get('https://rate.bot.com.tw/xrt?Lang=zh-TW')
print(driver.title)
html = driver.page_source
print(html)
soup = BeautifulSoup(driver.page_source, 'lxml')
print(soup.prettify())
with open('index.html', 'w', encoding='utf-8',) as file:
file.write(soup.prettify())
driver.quit()
Selenium有兩個系列的資料定位函式:
find_element()
: 用來取得網頁中的第一個定位到的HTML元素。find_elements()
: (名稱中多了一個s),用來取得所有網頁中定位到的元素。這兩個函式都可以使用下面方式來定位元素:
名稱 | 說明 |
---|---|
"id" |
使用id屬性值來定位元素 |
"name" |
使用name屬性值來定位元素 |
"xpath" |
使用XPath表達式來定位元素 |
"link text" |
使用超連結文字來定位元素 |
"partial link text" |
使用部分超連結文字來定位元素 |
"tag name" |
使用標籤名稱來定位元素 |
"class name" |
使用class屬性值來定位元素 |
"css selector" |
使用CSS選擇器來定位元素 |
ID = "id"
XPATH = "xpath"
LINK_TEXT = "link text"
PARTIAL_LINK_TEXT = "partial link text"
NAME = "name"
TAG_NAME = "tag name"
CLASS_NAME = "class name"
CSS_SELECTOR = "css selector"
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.common.exceptions import NoSuchElementException
from bs4 import BeautifulSoup
import requests
driver = webdriver.Chrome('chromedriver')
driver.implicitly_wait(10)
driver.get('https://rate.bot.com.tw/xrt?Lang=zh-TW')
print(driver.title)
html = driver.page_source
try:
download_csv = driver.find_element(By.LINK_TEXT, '下載 Excel (CSV) 檔')
print(download_csv.tag_name)
print(download_csv.get_attribute('href'))
download_csv.click()
except NoSuchElementException:
print('無法定位')
driver.quit()
備註:
下載的檔案名稱會跟直接從網站下載的檔名不同
名稱 | 說明 |
---|---|
click() |
點擊元素 |
click_and_hold() |
在元素上按住滑鼠左鍵 |
context_click() |
在元素上按住滑鼠右鍵 |
double_click() |
點擊兩次元素 |
move_to_element() |
移動滑鼠游標到元素中間 |
key_up() |
放開鍵盤的按鍵 |
key_down() |
按下鍵盤的按鍵 |
perform() |
執行所有儲存的動作 |
send_keys() |
送出按鍵到元素 |
release() |
在元素上鬆開滑鼠按鍵 |
driver.execute_script('window.scrollBy(0,1000)')
說明:
scrollBy(x,y)中,x為必須參數,表示向右滾動的像素值;y也為必須參數,表示向下滾動的像素值
driver.execute_script('window.scrollTo(0,1000)')
說明:
scrollTo(x,y) 中,x為必要參數,表示要在視窗顯示區左上角顯示的x坐標;y也為必要參數,表示要在視窗顯示區左上角顯示的y坐標
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
或
driver.execute_script('window.scrollTo(0,document.documentElement.scrollHeight)')
ENTER
SHIFT
LEFT_SHIFT
CONTROL
LEFT_CONTROL
ALT
LEFT_ALT
SPACE
名稱 | 說明 |
---|---|
ElementNotSelectableException | 選取的該元素不允許被選取 |
ElementNotVisibleException | 元素存在,但是不可見 |
ErrorInResponseException | 伺服器端回應錯誤 |
NoSuchElementException | 選取的元素不存在 |
TimeoutException | 超過時間限制 |