声明:本文只作学习研究,禁止用于非法用途,否则后果自负,如有侵权,请告知删除,谢谢!
项目场景:
这还是一个我刚初出茅庐的一个故事,那时候刚实习进的一家公司,第一天上班屁股还没坐热就被叫去开去,总监让我独立负责一个爬虫项目,大致需求:前端输入公司名称,后端获取数据并存储到mysql,然后爬虫根据公司名称爬取qcc上的数据信息,存入mysql再由后端获取相应信息传入前端显示,要求一个公司响应时间在5s以内,那个时候我并没有爬过qcc,心里还是有点虚的,时间要求是一个星期内上线测试,而且让我用自动化测试工具selenium(我当时这个根本没接触过呀~~),话不多说,下面慢慢叙述吧……
问题描述:
坑1
不登入状态下无法获取完整的电话和邮箱信息。
坑2
时不时弹出要你登入。
坑3
请求次数多了,每点一个栏目都会跳出要让你登入。
坑4
当请求到达一定次数,就会触发qcc的爬虫检测,必须要手动滑动检测的滑块验证码。
原因分析:
自然就是这个网站的反爬虫措施了,还有就是要让你登入才给你完整的数据。
解决方案:
所以,不管怎样,这个网站你要想拿完整的数据,就必须要登入,那么登入有几种方式呢?找了一个qcc的登入页面,这里可以看到三种直接登入,三种授权登入,我这里选择的是密码登入(当然其他方法也是可以)
既然要滑动滑块,且为乐避免过多划出导航条,就要先计算下需要滑动的距离,从下图可以看出,导航条长度348,滑块长度40,则需要滑动距离distance=348-40=308
然后我就用selenium模仿鼠标点击和移动,之前的代码找不到了,最后的结果是可以实现滑动滑块到终点,可以页面却无法实现登入,并出现异常。
这是由于系统页面检测到selenium启动浏览器时,参数window.navigator.webdriver默认位true
而我们自己的浏览器实际上是undefined或者false。
那么这个问题怎么解决,既然selenium给我们默认显示的true,那我们当然可以设置他不为true,只需要加上下面的参数即可
option.add_experimental_option('excludeSwitches', ['enable-automation']) # webdriver防检测
欧克! 到此为止就可以实现滑块的验证了!
这里附上测试的代码
import time
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
url = "https://www.qcc.com/user_login?back=%2F"
option = webdriver.ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation']) # webdriver防检测
option.add_argument("--no-sandbox")
option.add_argument("--disable-dev-usage")
desired_capabilities = DesiredCapabilities.CHROME # 修改页面加载策略
desired_capabilities["pageLoadStrategy"] = "none" # 注释这两行会导致最后输出结果的延迟,即等待页面加载完成再输出
driver = webdriver.Chrome(options=option)
driver.get(url)
time.sleep(2)
driver.find_element_by_id('normalLogin').click() # 点击密码登入
time.sleep(1)
#输入账号密码
driver.find_element_by_id('nameNormal').send_keys('123456')
driver.find_element_by_id('pwdNormal').send_keys('123456')
#获取滑块
button = driver.find_element_by_id('nc_1_n1z')
# 滑动滑块
ActionChains(driver).click_and_hold(button).perform()
ActionChains(driver).move_by_offset(xoffset=308, yoffset=0).perform()
ActionChains(driver).release().perform()
time.sleep(11111)