免責聲明:我們盡力確保本文的正確性,但本文不代表任何投資的建議,我們也無法擔保因使用本文的內容所造成的任何損失。如對本文內容有疑問,請詢問財經相關的專家。
在這個範例中,我們會前往內政部不動產資訊平台的網站抓法拍屋和金拍屋資料。我們有兩種策略,一個是直接利用該頁面的輸出 Excel 連結來取得數據,一個是直接爬頁面上的資料以取得數據。前者比較簡單,所以在本範例中我們採取前者。
我們這個爬蟲的動作拆解如下:
- 前往內政部不動產資訊平台中有關拍賣價格的頁面
- 拍賣有分法拍屋和金拍屋兩種,預設選項是全部,我們不調整
- 選取目標縣市,像是
新北市
- 選取目標鄉鎮市區,像是
板橋區
- 根據目前系統時間選擇三年內的時間,像本文完成於民國 107 年,就選
104
- 按下「查詢」鈕
- 按下「匯出 Excel」連結,取得資料
請讀者實地操作一下,感受這個過程。這裡的三年沒有什麼特別的意義,只是假定太久以前的行情參考性較低,讀者可自行調整時距。
由於整個程式碼較長,我們將其放在這裡;本文會拆解這個範例。
先引入所需的套件:
import datetime
import os
import time
from selenium import webdriver
將一些程式會用到的參數集中起來:
targetCounty = "新北市"
targetDistrict = "板橋區"
now = datetime.datetime.now()
threeYearAgo = str(now.year - 1911 - 3)
downloadPath = os.path.dirname(os.path.abspath(__file__))
雖然我們目前為了簡化範例,將參數的內容寫死在程式碼中。但我們保留日後將本程式參數化為命令列工具的彈性。
設置 Chrome 瀏覽器的偏好設定:
# Change Chrome options: (1) default downloading path, (2) disable popup blocking.
options = webdriver.ChromeOptions()
prefs = {}
prefs["download.default_directory"] = downloadPath
prefs["profile.default_content_settings"] = { "popups": 1 }
options.add_experimental_option('prefs', prefs)
在這裡我們設置可接受彈出視窗,這是因為在預設情形下,Chrome 會擋掉匯出的 Excel 文件。這個設置是經實測後修改的,不要死記這個設置。
使用 Chrome 做為我們的 driver:
# Create a new instance of the Chrome driver
driver = webdriver.Chrome(options=options)
前往相關頁面:
# Go to the foreclosure house page.
driver.get("https://pip.moi.gov.tw/V2/A/SCRA0601.aspx")
time.sleep(6) # Wait the page to fresh.
一樣要讓網頁更新一下頁面,故暫停程式數秒鐘。
最近 (西元 2020 年二月) 有讀者詢問到:因網站改版,前往目標網頁該網站會自動重導到另一個頁面,這時候要如何處理?這要看對方網站用什麼機制轉址。如果對方將轉址規則直接寫在後台,基本上是無解。如果對方在前端用 JavaScript 轉址,可以用 Sikuli 或按鍵精靈中止 JavaScript 執行。
以本例來說,直接重新訪問相同頁面即可:
# Trick for site redirecting.
driver.get("https://pip.moi.gov.tw/V2/A/SCRA0601.aspx")
time.sleep(6) # Wait the page to fresh.
第二次訪問網站時,就不會轉址了。但不是每個網站都能用這個方法來處理。此外,這個方式以後仍可能會失效,因為網頁爬蟲本來就要因網站更動而時時修改。
選擇目標縣市:
# Open the county menu.
countyMenu = driver.find_element_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlCity\"]")
countyMenu.click()
time.sleep(2) # Wait the page to fresh.
# Select targte county.
countyOptions = driver.find_elements_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlCity\"] option")
for option in countyOptions:
if targetCounty in option.text:
option.click()
break
time.sleep(4) # Wait the page to fresh.
這個動作實際上分為兩步,一開始先開啟選單,接著選擇項目。
選擇目標鄉鎮市區:
# Open the district menu.
districtMenu = driver.find_element_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlTown\"]")
districtMenu.click()
time.sleep(2) # Wait the page to fresh.
# Select targte district.
districtOptions = driver.find_elements_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlTown\"] option")
for option in districtOptions:
if targetDistrict in option.text:
option.click()
break
time.sleep(2) # Wait the page to fresh.
# Close district menu.
districtMenu.click()
time.sleep(2) # Wait the page to fresh.
這個動作可細分為三步,開啟選單、選擇目標項目、關閉選單。
選擇起始年份:
# Open the starting year menu.
startYearMenu = driver.find_element_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlYear1\"]")
startYearMenu.click()
time.sleep(2) # Wait the page to fresh.
# Select the starting year.
startYears = driver.find_elements_by_css_selector("select[name=\"ctl00$ContentPlaceHolder1$ddlYear1\"] option")
for option in startYears:
if threeYearAgo in option.text:
option.click()
break
time.sleep(2) # Wait the page to fresh.
# Close the starting year menu.
startYearMenu.click()
time.sleep(2) # Wait the page to fresh.
在此處,我們的想法是三年左右的行情有參考價值,讀者不一定要照我們的想法去寫程式。
送出「查詢」按鈕:
# Submit our query.
submitButton = driver.find_element_by_css_selector("[name=\"ctl00$ContentPlaceHolder1$btnQuery\"]")
submitButton.click()
time.sleep(4) # Wait the page to fresh.
每次執行此程式會有一個新的檔案可下載,我們移掉舊的:
# Remove old Excel file.
excelPath = os.path.join(downloadPath, "%5b拍賣拍定價%5d查詢結果下載.xls")
if os.path.exists(excelPath):
os.remove(excelPath)
下載此 Excel 檔:
# Download new Excel file.
link = driver.find_element_by_css_selector("#ctl00_ContentPlaceHolder1_btnExportExcel")
link.click()
time.sleep(5) # Wait the page to fresh.
最後不要忘了關掉瀏覽器:
# Close the browser.
driver.quit()