selenium 这个词很装逼 硒元素的意思
他的牛逼之处在于 直接模仿我们用户 操作浏览器
也就是说 他就是通过浏览器获取信息的 意味着根本不需要防止反爬虫策略——他就是一个通过浏览器访问页面的客户啊:)
当然了 弊端很明显——我们访问页面速度快嘛 相对于一般的爬虫
当然不怎么快 所以可能弥补的方法就是 多线程 开很多的浏览页面 当然对系统资源占用很大——浏览器还要负责渲染页面(当然你可以做点优化让他别加载你不感兴趣的内容)
所以用在那种需要复杂认证的场合 尤其是限制流量 固定时间访问次数的服务器——我们本来就快不了 selenium慢 反而一定程度上是件好事
当然有其他方式 弄代理也是ok的 问题是免费 稳定的代理真心不好找 找到了速度也不够 需要大量线程支持 这个没点基础搞不来 毕竟爬一天不到你就看到满屏幕的Exception:)
另外 这个 人挡杀人佛挡杀佛的神器 一般也用于做web页面的自动化测试 原因你懂的
好奇嘛?为啥他就能够模拟用户点击网页.输入账号密码自动登录.和各种神奇的功能
他最初的版本是通过注入js脚本(Hook in)的方法,然而太不稳定了 于是就针对市面上通行的几个浏览器,利用浏览器的API来操作
优点就是更加稳定 当然问题就是 更慢了 而且每种浏览器 套路不同
所以我们使用的时候 需要给每种浏览器创造实例 称为web driver 实例
那么 这项神器的工作原理是什么呢?
web driver是什么呢?你可以理解为 他就是一个封装了各种能够控制浏览器的工具的一个程序
当然你需要指定好 控制的是什么浏览器(chrome 还是 火狐 还是 IE edge还是…)
我们需要下载各种类型的web driver并且安装
这里提供
下载解压后,将chromedriver.exe , geckodriver.exe , Iedriver.exe发到Python的安装目录,然后再将Python的安装目录添加到系统环境变量的Path下面。(这个相信你已经做过了:)
回到我们代码上
控制浏览器 我们需要指定浏览器 方法就是 创造对应浏览器的实例 我们
这么写:
from selenium import webdriver
driver = webdriver.Firefox()
driver.get("http://www.python.org")
这个driver就是chrome浏览器的实例
而driver.get
操作流程是:会先等待你的目标网页加载完 然后再把控制权移交到你的控制代码上(就是模拟点击 爬取信息什么的 重头戏)
因此 对于AJAX太多的1网页 可能对selenium不是很友好(不知道那玩意加载完了没 当然 网速不太慢都问题不大 比如有个50兆)
不懂AJAX可以参考我的这篇文章:服务端编程(五)——AJAX
接下来 我们用xpath(一种标记网页控件位置的方法 可以当做是地址)地址来锁定“登录”按钮
xpath是用于标记XML的节点的 类似于HTML文件中DOM节点的标记方式
第一步 F12 然后用圈起来的工具
第二步 点击所需要锁定的控件
第三步 找到高亮显示的代码 就是对应控件的代码啦
第四步 找到其xpath地址 我们右键 点击“copy xpath”
然后我们就可以用selenium封装好的 通过xpath找element的方法啦
注意 别的索引方式(找element地址)的方式比如css选择器(selector)或者DOM节点寻找都是可行的
而且selenium有封装
但是xpath也是常规爬虫常见的元件锁定方式 这里就用xpath 有兴趣的可以了解py的xpath库
其他锁定element的方式 我后面会更新相应文章 毕竟很多时候 一个锁定方式不管用
login_button = driver.find_element_by_xpath('//*[@id="csdn_container_tool"]/div/ul/li[3]/a')
往函数find_element_by_xpath里面放 xpath就行了
很简单 调用click()方法就行了
找到登录按钮对象 我们就可以点击了:
login_button.click()
注意1 事实上 这么写会更加保险 这个后面会讲到 善用等待, 以防止页面还没有加载出来,你点空了的情况
wait_para = WebDriverWait(driver, 10)
login_button = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="csdn_container_tool"]/div/ul/li[3]/a')))
注意2 另外 这个点击的强大之处在于 当页面跳转 他只管当前的页面 不会说你重定向了 就没办法定位了
调用 send.keys 方法:
login_input_user = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="all"]')))
login_input_user.send_keys('2333')
# 手机号
login_input_psw = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="password-number"]')))
login_input_psw.send_keys('2333')
# 密码
login_button_3 = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div/div[1]/div[2]/div[5]/div/div[6]/div/button')))
login_button_3.click()
其他细节等以后我们学习深入了再讲 这里填代码完事
完整代码:
#-*- utf-8 -*-
from selenium.webdriver.common.action_chains import ActionChains
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from time import sleep
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
# 防止用selenium 被识别
option = ChromeOptions()
option.add_experimental_option('excludeSwitches', ['enable-automation'])
driver = Chrome(options=option)
driver.get("http://www.csdn.net")
wait_para = WebDriverWait(driver, 10)
login_button = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="csdn_container_tool"]/div/ul/li[3]/a')))
login_button.click()
login_button_2 = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div/div[1]/div[2]/div[5]/ul/li[2]/a')))
login_button_2.click()
login_input_user = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="all"]')))
login_input_user.send_keys('13713524786')
login_input_psw = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="password-number"]')))
login_input_psw.send_keys('137135Rzx8170069')
login_button_3 = wait_para.until(EC.element_to_be_clickable((By.XPATH, '//*[@id="app"]/div/div/div[1]/div[2]/div[5]/div/div[6]/div/button')))
login_button_3.click()
# 找到“嵌套”的iframe 也就是滑块页
try:
iframe = driver.find_element_by_xpath('//iframe')
except Exception as e:
print('get iframe failed: ', e)
iframe = 0
sleep(2)
driver.switch_to.frame(iframe)
try:
button = driver.find_element_by_xpath('//*[@id="nc_8_n1z"]')
except Exception as e:
print('get button failed: ', e)
button = 0
sleep(1)
action = ActionChains(driver)
action.click_and_hold(button).perform()
action.reset_actions()
for m in range(-20,20):
action.move_by_offset(m, 0).perform()
sleep(0.1)
注意 采用chrome78 以前的版本使用!
另外,