python實現問卷星網站的自動填寫


 

因為有一個課程要求進行調查數據的統計,而且小組里選用的是問卷星為平台,問題的形式比較單一,都為單選或多選,於是想到了用python實現一個腳本來代替小組里大家的手動填寫。。

大體上使用的就是python+Selenium+PIL+Tesseract

Selenium 是一種瀏覽器自動化測試框架,通過它檢索html與css代碼就可以輕松地找到想要的單選框、復選框、提交鍵等等,然后便可以自動化地實現點擊事件。但在這個過程中,還是有很多細節需要注意的。

例如我使用的firefox瀏覽器需要下載一個調試驅動插件 -> "geckodriver" 。

在最后提交數據的時候使用click()函數沒有起到跳轉頁面的作用,最后是使用send_keys(Keys.ENTER),也就是按Enter鍵才能實現。猜測是資料中提及的click只是觸發事件的方式的其中一種。

PIL (Python Image Library)則是python的一個圖形處理庫,在一段時間內提交的次數過多時,網站便會要求輸入驗證碼,這時候就要通過Selenium截取屏幕圖片然后通過PIL進行進一步的截取和優化圖片的效果。因為驗證碼當中可能會有干擾線、拉伸變形,這時候就要通過處理才能更好地判斷出當中的數據。

Tesseract 是一款由HP實驗室開發由Google維護的開源的光學字符識別引擎,PIL處理過后的圖片便是通過tesseract來與從github上已有的訓練數據進行匹配。

 

 1 # coding: utf-8
 2 
 3 from selenium import  webdriver
 4 from selenium.webdriver.common.by import By
 5 from selenium.webdriver.common.keys import Keys
 6 from selenium.webdriver.support.ui import Select
 7 from selenium.webdriver.common.action_chains import ActionChains
 8 from selenium.common.exceptions import NoAlertPresentException
 9 from PIL import Image,ImageEnhance
10 import random,os,time,pytesseract
11 
12 bs = webdriver.Firefox(executable_path="geckodriver")
13 bs.set_window_size(600,400)
14 
15 def func():
16     bs.get('https://www.wjx.cn/m/17854971.aspx/')
17     bs.find_elements_by_class_name("ui-radio")[0].click()
18     bs.find_elements_by_class_name("ui-checkbox")[1].click()
19     bs.find_elements_by_class_name("ui-radio")[2].click()
20     bs.find_elements_by_class_name("ui-checkbox")[4].click()
21     bs.find_elements_by_class_name("ui-checkbox")[5].click()
22     bs.find_elements_by_class_name("ui-checkbox")[8].click()
23     bs.find_elements_by_class_name("ui-checkbox")[11].click()
24     bs.find_elements_by_class_name("ui-radio")[6].click()
25     bs.find_elements_by_class_name("ui-checkbox")[random.randint(14, 17)].click()
26     try:
27         bs.find_element_by_id("yucinput").click()
28         time.sleep(2)
29         bs.get_screenshot_as_file('D://python_project//wholepage.png')
30         im = Image.open("D://python_project//wholepage.png")
31         box = (160, 180, 409, 308)
32         region = im.crop(box)
33         region.save("D://python_project//testwholepage.png")
34         im = Image.open("D://python_project//testwholepage.png")
35         im = im.convert("L")
36         threshold = 55
37         pixdata = im.load()
38         w, h = im.size
39         for y in range(h):
40             for x in range(w):
41                 if pixdata[x, y] < threshold: pixdata[x, y] = 0 else: pixdata[x, y] = 255 for y in range(1, h - 1): for x in range(1, w - 1): count = 0 if pixdata[x, y - 1] > 245:
42                     count = count + 1
43                 if pixdata[x, y + 1] > 245:
44                     count = count + 1
45                 if pixdata[x - 1, y] > 245:
46                     count = count + 1
47                 if pixdata[x + 1, y] > 245:
48                     count = count + 1
49                 if count > 2:
50                     pixdata[x, y] = 255
51 
52         im.save("D://python_project//newMethod.png")
53         img = Image.open("D://python_project//newMethod.png")
54         code = pytesseract.image_to_string(img, "eng")
55         newCode = ''
56         for c in code:
57             if(c.isalnum()):
58                 newCode += c
59         print(newCode)
60         bs.find_element_by_id("yucinput").send_keys(newCode)
61     except Exception:
62         print("other_func()")
63     finally:
64         bs.find_element_by_id("ctlNext").send_keys(Keys.ENTER)
65 
66 def func2():
67     bs.get('https://www.wjx.cn/m/17854971.aspx/')
68     bs.find_elements_by_class_name("ui-radio")[random.randint(0, 1)].click()
69     bs.find_elements_by_class_name("ui-checkbox")[random.randint(0, 2)].click()
70     bs.find_elements_by_class_name("ui-radio")[random.randint(2, 4)].click()
71     bs.find_elements_by_class_name("ui-checkbox")[random.randint(3, 6)].click()
72     bs.find_elements_by_class_name("ui-checkbox")[random.randint(7, 10)].click()
73     bs.find_elements_by_class_name("ui-checkbox")[random.randint(11, 13)].click()
74     bs.find_elements_by_class_name("ui-radio")[random.randint(5, 7)].click()
75     bs.find_elements_by_class_name("ui-checkbox")[random.randint(14, 17)].click()
76     bs.find_element_by_id("ctlNext").send_keys(Keys.ENTER)
77 
78 ''' def check(css):
79 
80     s = bs.find_elements_by_css_selector(css_selector=css).
81     if(len(s) == 0):
82         func2()
83     elif len(s) == 1:
84         func() '''
85 
86 while True:
87     try:
88         '''check("#yucinput")'''
89         func()
90     except Exception:
91         t = bs.switch_to_alert()
92         print(t.text)
93         t.accept()
94     time.sleep(2)

 

兩天趕出來的代碼。。非常混亂,最后還是可以跑起來。不過tesseract的准確率有點感人,大概是十個里面對上四個就不錯了。但是自動化處理起來的效率畢竟還是高於人工輸入的。最主要的原因我想還是在驗證碼圖片方面處理得不夠好,里面圖片處理首先是轉成灰度圖然后二值化然后對干擾線進行處理。而數據的輸入可以采取random.randint(x,y) 就可以讓數據平均顯示。

 

這是處理前

這是處理后

 

這已經是比較理想的情況 干擾線並沒有太多與字體重疊在一起

 

還有一處地方就是我是把py文件放在tesseract的安裝目錄下才能夠運行起來,但是我已經添加了tesseract環境變量。這里還是搞不懂的,還有具體圖像優化的算法 還是要再學習的。還有問卷星網站是一定時間內太多提交才會要求輸入驗證碼(當然,其實這個也可以設置為每次提交都要輸入驗證碼),所以就要使用異常的做區別對待,異常的使用不太熟,也是剛好運行起來了。。還要學習學習。不管這樣使用異常處理是否正確,不過也非常有用地幫助我理解異常這一概念了。

 

通過這兩天的調試,最明顯體會到的就是python作為一門腳本語言,真的非常神奇與方便。大量的現存庫可以幫助人們在短時間里做出一樣東西來。

 

 

參考資料:

Python+Selenium+PIL+Tesseract真正自動識別驗證碼進行一鍵登錄

 http://www.51testing.com/html/64/272264-200302.htmls

 

Selenium.click 不等於手動單擊

http://www.51testing.com/html/64/272264-200302.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM