#爬虫40selenium

selenium

selenium在爬虫体系中,主要是为了解决requests无法直接执行JS代码的问题。(因为requests只拿回响应数据,js代码还躺在脚本中未被触发执行,js可能的逻辑是会继续向服务器发送ajax请求加载数据,如果没有selenium,则只能手动使用requests再向ajax中的url再发请求)

selenium最常使用的场景是跟requests配合。

一、使用

1、安装,导入

pip install selenium

from selenium import webdriver

2、小例子

得到一个谷歌浏览对象

bro = webdriver.Chrome(executable_path=./chromedriver.exe)

执行这行代码的现象就跟人为手动双击谷歌浏览器效果一样。括号中的参数是指定浏览器的驱动所在路径,需要先去下载

国内镜像网站地址:

最新的版本去官网找:

针对谷歌浏览器,可以先在“帮助-关于”里面查看谷歌浏览器的版本,下载时选择低于此版本的最新版本即可。下载下来后解压得到一个exe的可执行文件,把它放在项目根路径下。

from selenium import webdriverbro = webdriver.Chrome(executable_path=./chromedriver.exe)  # 可以选择其他浏览器# 在浏览器地址栏里面输入百度urlbro.get(https://www.baidu.com/)# 找到百度的搜索输入框input_k = bro.find_element_by_id(kw)# 在框里输入pythoninput_k.send_keys(python)# 找到"百度一下"搜索按钮su = bro.find_element_by_id(su)# 点击“百度一下”按钮,整个过程由于速度很快,可以用time模块在各个步骤处睡2秒su.click()# 这里拿到的东西是执行过js代码后的bro.page_source# 关闭浏览器bro.close()

以下以打开百度首页登陆为例讲一些新的知识点。

from selenium import webdriverbro = webdriver.Chrome(executable_path=./chromedriver.exe)# 隐式等待5秒钟,意思是如果控件没有加载回来,我这儿等5秒后报错,如果5秒内加载回来了,则一加载回来马上继续往下执行。# 这行代码会等待后续所有的控件,如果没有这行代码,那么经常会报出找不到element的错误,就是因为代码在执行的时候控件还未加载bro.implicitly_wait(5)bro.get(https://www.baidu.com/)# 以a标签的内容来找d_button = bro.find_element_by_link_text(登录)d_button.click()accout_l = bro.find_element_by_id(TANGRAM__PSP_11__changePwdCodeItem)  # 找到账号登陆accout_l.click()login_u = bro.find_element_by_id(TANGRAM__PSP_11__userName)  # 找到用户名框login_u.send_keys(输入自己的账号) login_p = bro.find_element_by_id(TANGRAM__PSP_11__password)  # 找到密码框login_p.send_keys(输入自己的密码)submit = bro.find_element_by_id(TANGRAM__PSP_11__submit)  # 找到登录按钮submit.click()print(bro.get_cookies())  # 最终目的:登陆后拿到cookiebro.close()3、selenium 若干方法介绍1、bro.find_element_by_id()   # 通过id查找控件2、bro.find_element_by_link_text()  # 通过a标签内容找3、bro.find_element_by_partial_link_text()  # 通过a标签内容找,模糊匹配4、bro.find_element_by_tag_name()   # 通过标签名查找,比如li,img等5、bro.find_element_by_class_name()  # 类名6、bro.find_element_by_name()      # name属性# 参数写.类  #id,类只要写其中一个即可。配合空格(代表子子孙孙节点)和>(代表直接子节点)7、bro.find_element_by_css_selector()  8、bro.find_element_by_xpath()       # 通过xpaht选择器

find_element_by_xxx:返回一个对象

find_elements_by_xxx:查找到多个元素,结果为列表。以上方法都有对应的find_elements_by_xxx

同样的,每一个找到的标签,可以继续在此基础上继续查找

# 获取元素属性tag.get_attribute(href)  # 找当前控件的href属性对的值tag.text   # 获取当前控件的文本内容print(tag.id)   # 当前控件id号(不重要)print(tag.tag_name)  # 标签名(不重要)# 元素交互tag.send_keys()  # 往里面写内容tag.click()      # 点击控件tag.clear()      # 清空控件内容4、无界面浏览器(即:每次运行时不打开一个浏览器界面),使用的时候拷贝一下即可from selenium.webdriver.chrome.options import Optionsfrom selenium import webdriverchrome_options = Options()chrome_options.add_argument(window-size=1920x3000) #指定浏览器分辨率chrome_options.add_argument(--disable-gpu) #谷歌文档提到需要加上这个属性来规避bugchrome_options.add_argument(--hide-scrollbars) #隐藏滚动条, 应对一些特殊页面chrome_options.add_argument(blink-settings=imagesEnabled=false) #不加载图片, 提升速度# 上面是配置,主要是这句chrome_options.add_argument(--headless) #浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败bro=webdriver.Chrome(chrome_options=chrome_options,executable_path=./chromedriver.exe)bro.get(https://www.baidu.com/)print(bro.page_source)bro.close()# 特别注意关闭浏览器bro.close(),否则每次执行代码都会开一个谷歌浏览器的进程,会导致内存被撑爆掉。5、其他bro.execute_script(window.open())  # 执行jsbro.get_cookies()  # 获取cookie# 这4个常用于截验证码的图,然后发给打码平台去破解,会用到pillow模块bro.maximize_window()  # 窗口最大化,全屏bro.save_screenshot(./main.png) # 截取整个屏幕print(tag.location)  # 当前控件在页面位置print(tag.size)      # 标签的大小# 异常处理bro=webdriver.Chrome()try:    bro.get()except Exception as e:    print(e)finally:    # 无论是否出异常,最终都要关掉    bro.close()6、练习:爬取京东上的商品信息(很简单,大家可以自己试试实现)

用到的新知识点:

from selenium.webdriver.common.keys import Keysinput_k.send_keys(Keys.ENTER)  # 商品输入框输入完后按键盘enter键name = goods.find_element_by_css_selector(.p-name em).textprice = goods.find_element_by_css_selector(.p-price i).textimg = goods.find_element_by_css_selector(.p-img>a>img).get_attribute(src)url = goods.find_element_by_css_selector(.p-img>a).get_attribute(href)next_button = bro.find_element_by_partial_link_text(下一页)7、动作链

动作链一般用于图片的点击验证,或者滑动图片的场景上。

Chains(bro).click_and_hold(sourse) #点击并按住ActionChains(bro).move_by_offset(xoffset=20,yoffset=0).perform()  # 移动x轴和y轴的距离ActionChains(bro).move_to_element(tag).perform()  # 直接移动到某个控件上ActionChains(bro).move_to_element_with_offset(tag,xoffset=20,yoffset=0).perform() #移动到某个控件的某个位置ActionChains(bro).release()  释放动作链所有的动作最后都要执行perform(),真正的去执行

二、cookie池原理

1、用selenium写一个脚本,用一堆小号去登陆,登陆后拿回cookie(cookie里面含有登陆的账户信息)

2、放到redis当中

3、用django大家一个服务,往127.0.0.1/get中随机取回一个cookie

4、requests发送请求(带上cookie)爬数据,cookie失效则127.0.0.1/delete删除cookie

5、代理池也可以这么搭建服务,一堆的小号+一堆的代理IP,对方是很难封掉你的。(代理池可以到github上下载,后续再介绍)