位元詩人 [Selenium] 程式設計教學:如何到內政部不動產資訊平台抓法拍屋和金拍屋資料

Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Email

免責聲明:我們盡力確保本文的正確性,但本文不代表任何投資的建議,我們也無法擔保因使用本文的內容所造成的任何損失。如對本文內容有疑問,請詢問財經相關的專家。

在這個範例中,我們會前往內政部不動產資訊平台的網站抓法拍屋和金拍屋資料。我們有兩種策略,一個是直接利用該頁面的輸出 Excel 連結來取得數據,一個是直接爬頁面上的資料以取得數據。前者比較簡單,所以在本範例中我們採取前者。

我們這個爬蟲的動作拆解如下:

  1. 前往內政部不動產資訊平台中有關拍賣價格的頁面
  2. 拍賣有分法拍屋和金拍屋兩種,預設選項是全部,我們不調整
  3. 選取目標縣市,像是 新北市
  4. 選取目標鄉鎮市區,像是 板橋區
  5. 根據目前系統時間選擇三年內的時間,像本文完成於民國 107 年,就選 104
  6. 按下「查詢」鈕
  7. 按下「匯出 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()
關於作者

身為資訊領域碩士,位元詩人 (ByteBard) 認為開發應用程式的目的是為社會帶來價值。如果在這個過程中該軟體能成為永續經營的項目,那就是開發者和使用者雙贏的局面。

位元詩人喜歡用開源技術來解決各式各樣的問題,但必要時對專有技術也不排斥。閒暇之餘,位元詩人將所學寫成文章,放在這個網站上和大家分享。