--- title: Web Crawling Pro. tags: Projects, WebCrawler description: --- # 新北市政府社會局系統網路爬蟲專案 新北市政府社會局系統的資料刪除系統非常繁瑣,以人力方式執行非常耗時且不切實際,因此期待以網路爬蟲的方式來實作自動化系統來作業 ## 基本使用套件 在執行自動化作業時,主要使用Python Selenium此套件並執行於Chrome Webdriver ```python= from selenium import webdriver from bs4 import BeautifulSoup from selenium.webdriver.support.ui import Select from selenium.webdriver.common.by import By from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC ``` ## Step1.登入市府系統 首先,會先建立一個網頁模擬器方便後續程式碼執行時能夠被視覺化 ```python= driver = webdriver.Chrome('Webdriver放置路徑') driver.get('登入頁面') ``` 接著自動寫入帳號密碼與識別碼 ```python= # 輸入帳密及驗證碼並登入系統 account = driver.find_element_by_name('userID') account.clear() account.send_keys("輸入使用者帳號") password = driver.find_element_by_name('userPWD') password.clear() password.send_keys("輸入使用者密碼") ver_code = driver.find_element_by_xpath("//input[@name='captchaInput']") ver_code.clear() ver_code.send_keys(code) time.sleep(3) # 設定睡眠時間來等待驗證碼輸入 driver.find_element_by_id('ok').click() # 點擊後會自動切入新的頁面 ``` ![](https://i.imgur.com/9pDpxFN.png) 接著點選選擇的功能進入系統 ```python= driver.find_element_by_xpath("//a[@href='generalbudget/index.jsp?sysId=-17']").click() ``` ![](https://i.imgur.com/3aa5Fhn.jpg) ## Step2.選擇要進入的系統(公務\公彩) 在這裡我們要執行下拉式選單的自動化操作,當遇到下拉式選單時通常會先使用``Select``定位到該位址,並利用以下介紹的三種方法來做選擇 ```python= 問題:解決下拉式選單的選擇 <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <select name = "select_name"> <option value = "op_1">option 1</option> <option value = "op_2">選項 2</option> <option value = "op_3">選項三</option> </select> # -*- coding: utf-8 -*- from selenium import webdriver from selenium.webdriver.support.ui import Select driver = webdriver.Firefox() driver.get("TEST_URL") # 抓取下拉選單元件 select = Select(driver.find_element_by_name('select_name')) 抓取到下拉式元件後,可透過以下三種方法來選取下拉選單選項: 方法 1:透過 index 值選取資料, 執行後會選取「option 1」選項 select.select_by_index(0) 方法 2:透過 option 的 value 值選取資料, 執行後會選取「選項 2」選項 select.select_by_value("op_2") 方法 3:透過選項顯示的文字選取資料, 執行後會選取「選項三」選項 select.select_by_visible_text(u"選項三") ``` 執行程式碼為 ```python= driver.switch_to.frame("title") select = Select(driver.find_element_by_name('deptFullCode')) select.select_by_index(int(system)) driver.find_element_by_id("b1").click() driver.switch_to.default_content() ``` ![](https://i.imgur.com/VzDDNKf.png) 但在上述程式碼中可看到一開始做了一個切入框架``driver.switch_to.frame``的動作,這個指令是因為當程式碼被放置在``frame\iframe``內時無法被直接定位,須先切換到該框架中才能再重新定位,操作指令如下 ```python= driver.switch_to.frame(id/name/obj):可直接截取標單內的屬性 driver.switch_to.parent_frame():切到父frame driver.switch_to.default_content():跳回最外层的页面 ``` 此外,在執行網路爬蟲時常常會遇到另一個問題是需要給網頁時間去執行指令,若少了這一步奏有可能會讓程式無法順利執行。因此在遇到這類問題時會使用顯性等待ExpectedCondition與WebDriverWait來等待欄位展開並配合``until()``和``until_not()``方法,若成功執行EC內判斷則繼續執行代碼,否則輸出``TimeoutExpection`` 執行程式碼如下 ```python= # 切入目標框架中 driver.switch_to.frame("fbody") driver.switch_to.frame("menu") # 透過顯性等待來確認是否可以執行點擊 driver.find_element_by_id("menuTree").click() WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'menuTree_7_span'))) driver.find_element_by_id("menuTree_7_span").click() WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'menuTree_15_span'))) driver.find_element_by_id("menuTree_15_span").click() WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.ID, 'menuTree_18_span'))) driver.find_element_by_id("menuTree_18_span").click() ``` ![](https://i.imgur.com/m74OYZ4.png) ## Step3.執行資料刪除動作 進到該系統後會自動填入最初的設定資料型態並執行刪除 ```python= driver.switch_to.default_content() driver.switch_to.frame("fbody") driver.switch_to.frame("mainframe") driver.find_element_by_name("queryAll").click() queryCode = driver.find_element_by_name("q_codeId") queryCode.clear() queryCode.send_keys(delete_code) driver.find_element_by_name("querySubmit").click() ``` ![](https://i.imgur.com/4rkjGdX.png) 這邊會遇到一個問題就是刪除每一筆資料時會跳出小視窗詢問是否執行,該問題主要分三類 1. 警告訊息匡(alert) 2. 確認訊息匡(confirm) 3. 對話訊息匡(prompt) 解決方式:透過``switch_to_alert()``定位到``alert/confirm/prompt``,在執行以下動作 * switch_to_alert() #定位彈出對話 * text() #獲取對話方塊文字值 * accept() #相當於點選”確認” * dismiss() #相當於點選”取消” * send_keys() # 輸入值,這個alert和confirm沒有輸入對話方塊,所以這裡就不能用了,所以這裡只能使用在prompt這裡。 最後用迴圈判斷是否刪除完成並關閉視窗 ```python= stop = False while not stop: # 使用while loop解決,可不被單頁面所擁有的資料數侷限住 if driver.find_element_by_xpath("//tbody[@id='listTBODY']/tr[1]/td[1]").text == "1.": '''function''' driver.find_element_by_xpath("//tbody[@id='listTBODY']/tr[1]/td[1]").click() driver.find_element_by_name("delete").click() driver.switch_to_alert().accept() else: print("刪除程序已完成!!!") stop = True driver.close() driver.quit() ``` # Reference 基本的HTML語法 https://www.csie.ntu.edu.tw/~r91112/myDownload/WEB/html.html 基本Selenium語法 https://codertw.com/%E7%A8%8B%E5%BC%8F%E8%AA%9E%E8%A8%80/588694/ 解決無法定位的九種方法 https://www.jianshu.com/p/83087c24ab19 Python Selenium的等待方式 https://selenium-python-zh.readthedocs.io/en/latest/waits.html https://huilansame.github.io/huilansame.github.io/archivers/sleep-implicitlywait-wait 下拉式選單操作 https://jzchangmark.wordpress.com/2015/03/05/透過-selenium-操作下拉式選單-select/