2020上半年,新型冠狀病毒肺炎肆虐全國,大部分高校開學受到影響,各個高校成立了自身的疫情防控指揮部負責疫情防控工做,我所在高校的年級在疫情期間,要求全部學生進行健康打卡,打卡方式爲每日填寫問卷星發佈的問卷。css
每日須要進行打卡的問卷分爲三部分,第一部分爲基本狀況登記,一共7題。以下圖所示:前端
第二部分爲健康狀況登記,一共4題。以下圖所示:web
第三部分爲我的狀況登記,一共4題。以下圖所示:dom
以上15道題是學校要求天天都要完成的,實際上對於我來講,天天要填寫的內容差異並不大,正好疫情在家對Python語言有必定的學習和了解,所以,運用爬蟲技術處理問卷成爲了我那時在思考的問題。學習
能夠看出,問卷的15道題有單選(如第10題)、多選(如第8題)、也有下拉填空(如第6題)和單項填空(如第1題),這四種題目類型,基本覆蓋了全部問卷星經常使用的題目類型,所以探討該爬蟲的實現方式,受益不淺。ui
值得注意的是,問卷的發佈者是經過手機仍是電腦發佈的問卷對於爬蟲的部分實現代碼存在差別,不過底層邏輯是一致的,本文以問卷發佈者採用電腦端發佈問卷爲例。code
讓咱們開始吧!orm
首先,咱們導入一個關鍵庫,也就是爬蟲經常使用的selenium庫,導入後進行功能分析,咱們發如今第4題還須要用到一個random庫生成隨機範圍內體溫,隨後,在須要下拉的題目中須要selenium庫中的select方法。因而,代碼前端部分應該是:blog
from selenium import webdriver import random from selenium.webdriver.support.select import Select driver = webdriver.Chrome() driver.get('https://www.wjx.cn/jq/********.aspx')
經過網頁分析,不難看出,電腦端發佈的問卷,每個id都對應一道題,好比id=「div1」對應第一題,不一樣題目類型在下拉框中有不一樣描述,分析其不一樣描述而且獲取到所需數據是完成爬蟲的基礎,後續不作過多敘述。ip
問卷中,第1和第2題都很容易經過id獲取數據並進行輸入,代碼以下:
q1=driver.find_element_by_id('q1') q1.send_keys('***') q2=driver.find_element_by_id('q2') q2.send_keys('*********')
第3題是一個普通單選,但有時候出現的形式不必定須要選擇,而是默認直接選好,爲了爬蟲的通用性,採用了try...except...語句,讓爬蟲判斷這道題是否須要點擊。
try: q3=driver.find_elements_by_css_selector('#divquestion3 ul li') q3[0].click() except IndexError: pass
第4題和第5題都比較容易定位,注意的是第4題用到了random庫,讓天天的問卷有不一樣的體溫,更加天然:
q4=driver.find_element_by_id('q4') q4.send_keys(str(round(random.uniform(35.6,36.9),1))) q5=driver.find_element_by_id('q5') q5.click()
第6題的代碼實現是最爲複雜的部分,由於第6題點開後是多級下拉選擇,畫風是這樣的:
說實話,第6題的實現問題我試了不少方法,可是都不能正確運行,最終在CSDN上找到了一個計算機專業的大神,獲得了大神的幫助,那就是selenium庫中的select方法,實現起來以下圖所示。這裏面最騷的操做在於元素的定位,也就是switch_to.frame("PDF_i_chezchenz")語句,另外要注意的就是*號部分替換的文字須要和下拉列表的可選項保持一致哦。
q6=driver.find_element_by_id('q6') q6.click() driver.switch_to.frame("PDF_i_chezchenz") a = driver.find_element_by_id("province") Select(a).select_by_value("**") a = driver.find_element_by_id("city") Select(a).select_by_value("**") a = driver.find_element_by_id("area") Select(a).select_by_value("***") a = driver.find_element_by_class_name("submitbutton") a.click() driver.switch_to.default_content()
第七、八、9題的多選平淡無奇,直接選就是:
q7=driver.find_elements_by_css_selector('#divquestion7 ul li') q7[4].click() q8=driver.find_elements_by_css_selector('#divquestion8 ul li') q8[5].click() q9=driver.find_elements_by_css_selector('#divquestion9 ul li') q9[5].click()
第10到14題的單選問卷星並不走尋常路,find_elements_by_()方法開始無論用了,這時須要用execute_script()進行操做。
q10='document.getElementById("q10_2").click()' driver.execute_script(q10) q11='document.getElementById("q11_1").click()' driver.execute_script(q11) q12='document.getElementById("q12_1").click()' driver.execute_script(q12) q13='document.getElementById("q13_2").click()' driver.execute_script(q13) q14='document.getElementById("q14_1").click()' driver.execute_script(q14)
最後填空題和第1題的實現方法是一致的。
q15=driver.find_element_by_id('q15') q15.send_keys('**********************')
前面說到,手機和電腦端發佈的問卷實現方法有些不一致,這裏的不一致體如今標籤的不一樣,其餘的邏輯是一致的,現將手機版本的問卷爬蟲所有貼上,能夠與上面電腦版本的進行對比哦。
from selenium import webdriver import random from selenium.webdriver.support.select import Select driver = webdriver.Chrome() driver.get('https://www.wjx.cn/jq/73635984.aspx') q1=driver.find_element_by_id('q1') q1.send_keys('***') q2=driver.find_element_by_id('q2') q2.send_keys('**********') q4=driver.find_element_by_id('q4') q4.send_keys(str(round(random.uniform(35.6,37.2),1))) gddxt=driver.find_elements_by_class_name('label') gddxt[0].click() gddxt[19].click() gddxt[20].click() gddxt[21].click() gddxt[24].click() gddxt[26].click() gddxt[27].click() dxt=driver.find_elements_by_class_name('ui-checkbox') dxt[4].click() dxt[10].click() dxt[16].click() q15=driver.find_element_by_id('q15') q15.send_keys('*********************') q6=driver.find_element_by_id('q6') q6.click() driver.switch_to.frame("yz_popwinIframe") a = driver.find_element_by_id("province") Select(a).select_by_value("**") a = driver.find_element_by_id("city") Select(a).select_by_value("***") a = driver.find_element_by_id("area") Select(a).select_by_value("*****") a = driver.find_element_by_class_name("button_a") a.click() driver.switch_to.default_content() q5=driver.find_element_by_id('q5') q5.click()