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()