用Python 3 + Selenium 3實現漢堡王客戶調查的自動填寫,可以用來作為 python selenium的入門學習實現腳本,列舉了幾個比較不太好弄的知識點。
上代碼:
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import unittest
from selenium.webdriver.common.keys import Keys
import time
class TellBK(unittest.TestCase):
def setUp(self) -> None:
self.driver = webdriver.Firefox()
self.driver.implicitly_wait(30)
def test_fillFeedBack(self):
driver = self.driver
driver.maximize_window()
driver.get('https://tellburgerking.com.cn')
time.sleep(10)
# Page 1 - Welcome
# 點擊繼續
element = WebDriverWait(driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//input[@id="NextButton"]')))
element.click()
# Page 2 - Fill the codes and continue
# 填寫調查代碼, FeedbackCode.txt保存調查代碼,3個一組,空格分開
codefile = open('FeedbackCode.txt', 'r')
feedbackcode = codefile.read().split(" ")
codefile.close()
for i in range(len(feedbackcode)):
driver.find_element_by_xpath('//input[@id="CN{}"]'.format(i+1)).send_keys(feedbackcode[i])
# 點擊開始
driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
# Page 3 - Page 12
radiovaluelist = [('simpleInput rblv', 2), ('simpleInput rblv', 2), ('simpleInput rblv', 1),
('simpleInput rbl', 5), ('simpleInput rbl', 5), ('simpleInput rbl', 5),
('simpleInput rbl', 5), ('simpleInput rbl', 9), ('simpleInput rbl', 2),
('simpleInput rbl', 5)]
for radiovalue in radiovaluelist:
self.selectRadiosSubmit(radiovalue)
# Page 13 - Say something
with open('HappyReason.txt') as filereason:
reasontext = filereason.read()
driver.find_element_by_xpath('//textarea[@id="S000122"]').send_keys(reasontext)
# Next
driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
# Page 14 - What you ordered
element = self.driver.find_element_by_id("R000091")
self.driver.execute_script("arguments[0].click();", element)
driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
element = self.driver.find_element_by_id("R000097")
self.driver.execute_script("arguments[0].click();", element)
driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
# Page 16 - Page 19
radiovaluelist = [('simpleInput rbl', 1), ('simpleInput rblv', 5),
('simpleInput rblv', 2), ('simpleInput rblv', 1), ]
for radiovalue in radiovaluelist:
self.selectRadiosSubmit(radiovalue)
# Page - Gender and age
driver.find_element_by_xpath("//select[@id='R069000']").find_element_by_xpath("//option[@value='2']").click()
time.sleep(3)
driver.find_element_by_xpath("//select[@id='R070000']").find_element_by_xpath("//option[@value='3']").click()
driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
time.sleep(3)
# Page - Share zip code
driver.find_element_by_xpath('//input[@id="NextButton"]').click()
time.sleep(10)
# Page - Last page get screenshot
driver.get_screenshot_as_file('%s.png' % time.strftime("%Y%m%d.%H.%M.%S"))
def selectRadiosSubmit(self, radioattribute):
elements = self.driver.find_elements_by_xpath(
'//input[@class="{}" and @value="{}"]'.format(radioattribute[0], radioattribute[1]))
print(len(elements))
for element in elements:
self.driver.execute_script("arguments[0].click();", element)
time.sleep(3)
self.driver.find_element_by_xpath('//input[@id="NextButton"]').submit()
time.sleep(3)
def tearDown(self) -> None:
self.driver.quit()
if __name__ == "__main__":
unittest.main()
需要注意的幾個問題:
- 漢堡王客戶調查頁面的Radio是沒辦法直接調用click的, 會拋‘could not be scrolled into view’ Exception.需要調用Javascript進行點擊。沒有試ActionChains可否操作, 同樣的問題對於checkbox也是,需要調用Javascript進行點擊。
- 漢堡王客戶調查頁面的Radio也是有區別的,有的class = 'simpleInput rbl', 有的class = 'simpleInput rblv'
- 頁面上多組Radio的ID值是變動的,不能直接使用,所以用了class 加 value定位。原本我打算用ends-with的,但是試了好像不行。這個ends-with對於xpath的定位比較弱,不太好匹配上,即使你覺得本應該沒問題, 不建議使用。
- selenimu的上腳本點擊的速度是遠超過頁面響應速度的,所以必要的時候,要強制time.sleep(), 或者使用WebDriver的顯示等待。建議每個action后都稍微sleep下,特別是頁面跳轉的時候。對於關鍵元素WebDriver進行check
- 這些頁面里面沒有iframe,所以你不會碰到iframe導致的元素找不到的問題。
- 還需要注意button上的click()和submit()方法是略有不同的。click()對於button來說都可以使用,submit()用於在點擊button后提交表單數據,使用需要滿足一定的條件, 比如按鈕的type='submit',而且這個按鈕要在<form> tag里面。
- 我沒有添加exception的處理,這里的代碼只是基礎代碼,可以自行優化,以及組織。
- 最后的驗證碼是保存在一個png文件里面的,需要自己手動去查看。沒來得及是實現和抓取。
