ToB企服应用市场:ToB评测及商务社交产业平台

标题: 爬虫之selenium [打印本页]

作者: 半亩花草    时间: 2022-9-6 07:14
标题: 爬虫之selenium
目录

selenium介绍

由于requests模块不能执行js,有的页面内容,我们在浏览器中可以看到,但是请求下来没有。
selenium模块:模拟操作浏览器,完成人的行为。
selenium本质是通过驱动浏览器,完全模拟浏览器的操作,比如跳转、输入、点击、下拉等,来拿到网页渲染之后的结果,可支持多种浏览器。
模块安装:
  1. pip install selenium
复制代码
下载驱动
驱动浏览器需要下载相应的驱动,谷歌要下谷歌的驱动,火狐要下火狐的驱动,并且版本要与当前浏览器对应。
这里我选择谷歌浏览器,首先查看当前谷歌浏览器的版本:

版本:

下载驱动,地址:CNPM Binaries Mirror (npmmirror.com),一定要下载对应的版本驱动,比如我谷歌浏览器版本为103.0.5060.134,就要下103.0.5060.134的驱动

下载对应操作系统即可。
基本使用

导入模块:
  1. from selenium import webdriver
复制代码
初始化(打开浏览器):
  1. browser = webdriver.Chrome(executable_path='驱动路径')
复制代码
  1. # 不写路径,要放到项目路径下或环境变量中
  2. browser = webdriver.Chrome()
复制代码
在地址栏输入地址:
  1. browser.get('http://www.baidu.com')
复制代码
关闭标签:
  1. browser.close()
复制代码
关闭浏览器:
  1. browser.quit()
复制代码
selenium用法

元素操作

操作浏览器页面中的标签。
1.搜索标签
新版本:by=根据什么查找,value=查找的值
by的参数含义By.ID根据标签id属性查找By.LINK_TEXT根据a标签的文字查找By.PARTIAL_LINK_TEXT根据a标签的文字模糊匹配By.TAG_NAME根据标签名查找By.CLASS_NAME根据标签class属性查找By.NAME根据标签name属性查找By.CSS_SELECTOR根据css选择器查找By.XPATH根据xpath查找
  1. from selenium.webdriver.common.by import By
  2. # 查找网页中id为'login'的标签
  3. tag = browser.find_element(by=By.ID, value='login')
  4. # 查找网页中class为'login'的所有标签
  5. tags = browser.find_elements(By.CLASS_NAME, value='login')
  6. # 查找网页div标签中class属性为'dd'的标签
  7. tag = browser.find_element(by=By.CSS_SELECTOR, value='div .dd')
  8. # 查找网页中a标签文字为'登录'的标签
  9. tag = browser.find_element(by=By.LINK_TEXT, value='登录')
复制代码
老版本:
  1. browser.find_element_by_id()  # 根据id
  2. browser.find_element_by_link_text()  # 根据a标签的文字
  3. browser.find_element_by_partial_link_text()  # 根据a标签的文字模糊匹配
  4. browser.find_element_by_tag_name()  # 根据标签名
  5. browser.find_element_by_class_name()  # 根据类名
  6. browser.find_element_by_name()  # 根据name属性
  7. browser.find_element_by_css_selector()  # css选择器
复制代码
2.点击标签
  1. # 查找网页中id为'login'的标签
  2. tag = browser.find_element(by=By.ID, value='login')
  3. # 标签点击
  4. tag.click()
复制代码
3.向输入框中写内容
  1. tag = browser.find_element(by=By.ID, value='inputTag')
  2. tag.send_keys('内容')
复制代码
4.清空
  1. tag = browser.find_element(by=By.ID, value='inputTag')
  2. tag.clear()
复制代码
举例:打开百度搜索'博客园':
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. # 打开浏览器
  4. browser = webdriver.Chrome()
  5. # 输入网址进入
  6. browser.get('http://www.baidu.com')
  7. # 查找百度输入框
  8. word = browser.find_element(By.ID, 'kw')
  9. # 输入框添加内容
  10. word.send_keys('博客园')
  11. # 查找搜索按钮
  12. btn = browser.find_element(By.ID, 'su')
  13. # 点击搜索按钮
  14. btn.click()
  15. # 等待2秒关闭浏览器
  16. import time
  17. time.sleep(2)
  18. browser.quit()
复制代码
等待元素被加载

程序操作页面非常快,所以在取每个标签的时候,标签可能没有加载好,取标签时就会报错,所以需要设置等待时间。
如果标签找不到,就会等待,还找不到就会报错:
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. # 打开浏览器
  4. browser = webdriver.Chrome()
  5. # 找不到标签就等待2秒
  6. browser.implicitly_wait(2)
  7. # 输入网址进入
  8. browser.get('http://www.baidu.com')
  9. # 查找百度输入框
  10. word = browser.find_element(By.ID, 'kw')
  11. # 输入框添加内容
  12. word.send_keys('博客园')
  13. # 查找搜索按钮
  14. btn = browser.find_element(By.ID, 'su')
  15. # 点击搜索按钮
  16. btn.click()
  17. # 找到能进入博客园的a标签
  18. cnblog = browser.find_element(By.LINK_TEXT, '博客园')
  19. # 进入博客园
  20. cnblog.click()
  21. # 等待2秒关闭浏览器
  22. import time
  23. time.sleep(2)
  24. browser.quit()
复制代码
元素各项属性

标签对象调用含义标签对象.location标签所在位置标签对象.size标签大小(高宽)标签对象.id标签id号(随机给的),不是id属性标签对象.tag_name标签名标签对象.get_attribute('属性')标签属性值
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. # 打开浏览器
  4. browser = webdriver.Chrome()
  5. # 输入网址进入
  6. browser.get('http://www.baidu.com')
  7. # 查找百度输入框
  8. word = browser.find_element(By.ID, 'kw')
  9. print(word.location)  # 标签所在位置,{'x': 298, 'y': 188}
  10. print(word.size)  # 标签大小,{'height': 44, 'width': 550}
  11. print(word.id)  # 标签id号,不是id属性
  12. print(word.tag_name)  # 标签名字,input
  13. print(word.get_attribute('class'))  # 获取标签的class属性值,s_ipt
  14. browser.quit()
复制代码
执行js代码

执行js用途:
滚动条到最底部
  1. from selenium import webdriver
  2. # 打开浏览器
  3. browser = webdriver.Chrome()
  4. # 输入网址进入
  5. browser.get('https://www.cnblogs.com/')
  6. # 滚动条到最底部
  7. browser.execute_script('scrollTo(0,document.body.scrollHeight)')
  8. import time
  9. time.sleep(3)
  10. browser.quit()
复制代码
打开新标签
  1. from selenium import webdriver
  2. # 打开浏览器
  3. browser = webdriver.Chrome()
  4. # 输入网址进入
  5. browser.get('https://www.cnblogs.com/')
  6. # 打开新标签
  7. browser.execute_script('window.open()')
  8. import time
  9. time.sleep(3)
  10. browser.quit()
复制代码
切换选项卡

浏览器打开了多个选项卡,需要切换时:
  1. browser.switch_to.window(browser.window_handles[1])
复制代码
  1. # 已弃用的方法
  2. browser.switch_to_window(browser.window_handles[1])
复制代码
browser.window_handles[0]代表第一个选项卡
browser.window_handles[1]代表第二个选项卡
  1. from selenium import webdriver
  2. import time
  3. # 打开浏览器
  4. browser = webdriver.Chrome()
  5. # 进入博客园
  6. browser.get('https://www.cnblogs.com/')
  7. time.sleep(1)
  8. # 打开新标签
  9. browser.execute_script('window.open()')
  10. # 切换到新标签
  11. browser.switch_to.window(browser.window_handles[1])
  12. # 新标签进入百度
  13. browser.get('https://www.baidu.com/')
  14. time.sleep(1)
  15. # 切换回博客园
  16. browser.switch_to.window(browser.window_handles[0])
  17. time.sleep(2)
  18. browser.quit()
复制代码
浏览器前进后退

浏览器前进:
  1. browser.forward()
复制代码
浏览器后退:
  1. browser.back()
复制代码
无界面浏览器

不显示的打开浏览器的图形化界面,还能获取数据
  1. from selenium import webdriver
  2. from selenium.webdriver.chrome.options import Options
  3. chrome_options = Options()
  4. chrome_options.add_argument('window-size=1920,3000')  # 指定浏览器分辨率
  5. chrome_options.add_argument('--disable-gpu')  # 谷歌文档提到需要加上这个属性来规避bug
  6. chrome_options.add_argument('--hide-scrollbars')  # 隐藏滚动条, 应对一些特殊页面
  7. chrome_options.add_argument('blink-settings=imagesEnabled=false')  # 不加载图片, 提升速度
  8. chrome_options.add_argument('--headless')  # 浏览器不提供可视化页面. linux下如果系统不支持可视化不加这条会启动失败
  9. browser = webdriver.Chrome(options=chrome_options)
  10. browser.get('https://www.cnblogs.com/')
  11. print(browser.page_source)  # 当前页面的内容(html内容)
  12. browser.quit()
复制代码
xpath的使用

简单介绍

XPath 是一门在 XML 文档中查找信息的语言。
表达式描述nodename选取此标签的所有子标签。如:div,选取div标签下的子标签/找当前路径下的标签//找当前路径子子孙孙下的标签.表示当前路径..表示上一次@选取属性。举例:
表达式描述//*所有标签//head所有head标签//div/a所有div标签下的a标签//a[@]所有class属性为'a1'的a标签/div所有最外层的div标签//head/text()所有head标签的文本内容//div/a[1]div标签下的第一个a标签//div/a[contains(@class,"li")]多个属性要用containsselenium中使用

网页中打开F12,找到标签,右键-->复制-->复制 Xpath,把值用在代码中即可。
  1. from selenium.webdriver.common.by import By
  2. from selenium import webdriver
  3. browser = webdriver.Chrome()
  4. browser.get('https://www.cnblogs.com/')
  5. res = browser.find_element(By.XPATH, '//*[@id="post_list"]/article[1]/section/div')
  6. print(res.text)
复制代码

异常处理

由于有时候程序操作浏览器过快,有些标签会找不到等一些情况会出现报错,这时候可以用异常处理:
  1. from selenium.common.exceptions import TimeoutException, NoSuchElementException, NoSuchFrameException
  2. from selenium import webdriver
  3. from selenium.webdriver.common.by import By
  4. # 打开浏览器
  5. browser = webdriver.Chrome()
  6. try:
  7.     # 输入网址进入
  8.     browser.get('http://www.baidu.com')
  9.     # 查找百度输入框
  10.     word = browser.find_element(By.ID, 'kw')
  11.     # 输入框添加内容
  12.     word.send_keys('博客园')
  13.     # 查找搜索按钮
  14.     btn = browser.find_element(By.ID, 'su')
  15.     # 点击搜索按钮
  16.     btn.click()
  17.     # 找到能进入博客园的a标签
  18.     cnblog = browser.find_element(By.LINK_TEXT, '博客园')
  19. except Exception as e:
  20.     print(e)
  21. finally:  # 不管报不报错最后都关闭浏览器
  22.     # 等待2秒关闭浏览器
  23.     import time
  24.     time.sleep(2)
  25.     browser.quit()
复制代码
登录获取cookie保存

获取浏览器所有cookie:
  1. cookies = browser.get_cookies()
  2. print(cookies)
复制代码
登录博客园并保存cookie:
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. import time
  4. # 打开浏览器
  5. browser = webdriver.Chrome()
  6. browser.implicitly_wait(2)
  7. try:
  8.     # 进入博客园
  9.     browser.get('https://www.cnblogs.com/')
  10.     # 查找登录按钮
  11.     login_btn = browser.find_element(By.LINK_TEXT, '登录')
  12.     login_btn.click()
  13.     # 查找用户名和密码输入框
  14.     username = browser.find_element(By.ID, 'mat-input-0')
  15.     password = browser.find_element(By.ID, 'mat-input-1')
  16.     # 输入用户名密码
  17.     username.send_keys('xx')
  18.     password.send_keys('123')
  19.     btn = browser.find_element(By.CSS_SELECTOR, 'body > app-root > app-sign-in-layout > div > div > app-sign-in > app-content-container > div > div > div > form > div > button')
  20.     btn.click()
  21.     # 可能要验证,睡眠一下手动过验证
  22.     time.sleep(10)
  23.     # 保存cookie
  24.     import json
  25.     cookies = browser.get_cookies()
  26.     with open('cnblog.json', 'w', encoding='utf-8') as f:
  27.         json.dump(cookies, f)
  28. except Exception as e:
  29.     print(e)
  30. finally:  # 不管报不报错最后都关闭浏览器
  31.     # 等待2秒关闭浏览器
  32.     time.sleep(2)
  33.     browser.quit()
复制代码
如果标签不好找出来,可以打开F12,找到标签位置,复制css选择器:

通过cookie达成登录效果
  1. from selenium import webdriver
  2. import time
  3. # 打开浏览器
  4. browser = webdriver.Chrome()
  5. browser.implicitly_wait(2)
  6. try:
  7.     # 进入博客园
  8.     browser.get('https://www.cnblogs.com/')
  9.     # 此时还不是登录后的状态
  10.     time.sleep(2)
  11.     # 拿出cookie
  12.     import json
  13.     with open('cnblog.json', 'r', encoding='utf-8') as f:
  14.         cookies = json.load(f)
  15.     # cookie保存时是列表套字典,但写入cookie需要用字典格式,所以用循环
  16.     for cookie in cookies:
  17.         browser.add_cookie(cookie)
  18.     # cookie全写入后刷新页面
  19.     browser.refresh()
  20.     # 此时是登录后的状态
  21. except Exception as e:
  22.     print(e)
  23. finally:  # 不管报不报错最后都关闭浏览器
  24.     # 等待2秒关闭浏览器
  25.     time.sleep(2)
  26.     browser.quit()
复制代码
动作链

模拟按住鼠标拖动的效果,或者是在某个标签上的某个位置点击的效果,主要用来做验证码的破解(滑动验证码)。
导入:
  1. from selenium.webdriver import ActionChains
复制代码
初始化:得到动作链对象
  1. actions = ActionChains(浏览器对象)
复制代码
添加动作的方法:
  1. # 按住标签的动作,按住source
  2. actions.click_and_hold(sourse)
  3. # 移动标签的动作,source移到target
  4. actions.drag_and_drop(sourse, target)
  5. # 移动标签的动作,按住source移到target并偏移
  6. actions.click_and_hold(sourse).drag_and_drop_by_offset(target, xoffset, yoffset)
  7. # 移动标签的动作,按住source并移动(x, y)
  8. actions.click_and_hold(sourse).move_by_offset(xoffset, yoffset)
  9. # 松开动作
  10. actions.release()
复制代码
执行动作:上述方法需要语句执行动作
  1. # 执行动作
  2. actions.perform()
复制代码
实战:
方式一:基于同一个动作链串行执行
  1. from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ActionChainsimport timebrowser = webdriver.Chrome()browser.implicitly_wait(5)browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')# 页面有一个iframe标签,需要切换进去browser.switch_to.frame('iframeResult')# 可移动标签source = browser.find_element(By.ID, 'draggable')# 目标标签target = browser.find_element(By.ID, 'droppable')# 拿到动作链对象actions = ActionChains(browser)# 移动动作actions.drag_and_drop(source, target)# 执行动作
  2. actions.perform()time.sleep(2)browser.quit()
复制代码
  1. from selenium import webdriverfrom selenium.webdriver.common.by import Byfrom selenium.webdriver import ActionChainsimport timebrowser = webdriver.Chrome()browser.implicitly_wait(5)browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')browser.switch_to.frame('iframeResult')source = browser.find_element(By.ID, 'draggable')target = browser.find_element(By.ID, 'droppable')# 拿到动作链对象actions = ActionChains(browser).click_and_hold(source)actions.drag_and_drop_by_offset(target, 10, 10)# 执行动作
  2. actions.perform()time.sleep(2)browser.quit()
复制代码
方式二:不同的动作链,每次移动的位移都不同
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. from selenium.webdriver import ActionChains
  4. import time
  5. browser = webdriver.Chrome()
  6. browser.implicitly_wait(5)
  7. browser.get('http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable')
  8. browser.switch_to.frame('iframeResult')
  9. source = browser.find_element(By.ID, 'draggable')
  10. target = browser.find_element(By.ID, 'droppable')
  11. ActionChains(browser).click_and_hold(source).perform()
  12. distance = target.location['x'] - source.location['x']  # 两个控件的x轴的距离
  13. track = 0
  14. while track < distance:
  15.     ActionChains(browser).move_by_offset(xoffset=20, yoffset=0).perform()
  16.     track += 20
  17. ActionChains(browser).release().perform()
  18. time.sleep(2)
  19. browser.quit()
复制代码
打码平台使用(验证码破解)

简单的数字字母组合可以使用图像识别(python 现成模块),但是成功率不高,所以可以使用第三方打码平台(破解验证码平台),花钱,把验证码图片给它,它给你识别完,返回给你。
超级鹰验证码识别-专业的验证码云端识别服务,让验证码识别更快速、更准确、更强大 (chaojiying.com)
超级鹰开发文档:
  1. import requests
  2. from hashlib import md5
  3. class ChaojiyingClient:
  4.     def __init__(self, username, password, soft_id):
  5.         self.username = username
  6.         password = password.encode('utf8')
  7.         self.password = md5(password).hexdigest()
  8.         self.soft_id = soft_id
  9.         self.base_params = {
  10.             'user': self.username,
  11.             'pass2': self.password,
  12.             'softid': self.soft_id,
  13.         }
  14.         self.headers = {
  15.             'Connection': 'Keep-Alive',
  16.             'User-Agent': 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0)',
  17.         }
  18.     def PostPic(self, im, codetype):
  19.         """
  20.         im: 图片字节
  21.         codetype: 题目类型 参考 http://www.chaojiying.com/price.html
  22.         """
  23.         params = {
  24.             'codetype': codetype,
  25.         }
  26.         params.update(self.base_params)
  27.         files = {'userfile': ('ccc.jpg', im)}
  28.         r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, files=files,
  29.                           headers=self.headers)
  30.         return r.json()
  31.     def PostPic_base64(self, base64_str, codetype):
  32.         """
  33.         im: 图片字节
  34.         codetype: 题目类型 参考 http://www.chaojiying.com/price.html
  35.         """
  36.         params = {
  37.             'codetype': codetype,
  38.             'file_base64': base64_str
  39.         }
  40.         params.update(self.base_params)
  41.         r = requests.post('http://upload.chaojiying.net/Upload/Processing.php', data=params, headers=self.headers)
  42.         return r.json()
  43.     def ReportError(self, im_id):
  44.         """
  45.         im_id:报错题目的图片ID
  46.         """
  47.         params = {
  48.             'id': im_id,
  49.         }
  50.         params.update(self.base_params)
  51.         r = requests.post('http://upload.chaojiying.net/Upload/ReportError.php', data=params, headers=self.headers)
  52.         return r.json()
  53. if __name__ == '__main__':
  54.     chaojiying = ChaojiyingClient('超级鹰用户名', '超级鹰用户名的密码', '96001')  # 用户中心>>软件ID 生成一个替换 96001
  55.     im = open('a.jpg', 'rb').read()  # 本地图片文件路径 来替换 a.jpg 有时WIN系统须要//
  56.     print(chaojiying.PostPic(im, 1902))  # 1902 验证码类型  官方网站>>价格体系 3.4+版 print 后要加()
  57.     # print chaojiying.PostPic(base64_str, 1902)  #此处为传入 base64代码
复制代码
用超级鹰破解超级鹰验证码并登录:
  1. from selenium import webdriver
  2. from selenium.webdriver.common.by import By
  3. import time
  4. from PIL import Image
  5. # 验证码获取
  6. def get_code():
  7.     browser.save_screenshot('main.png')  # 把当前页面截图
  8.     img = browser.find_element(By.XPATH, '/html/body/div[3]/div/div[3]/div[1]/form/div/img')  # 获取图片标签
  9.     location = img.location  # 图片位置
  10.     size = img.size  # 图片宽高
  11.     # 使用pillow扣除大图中的验证码,pip install pillow
  12.     img_tu = (
  13.         int(location['x']) * 1.25,
  14.         int(location['y']) * 1.25,
  15.         int(location['x'] + size['width']) * 1.25,
  16.         int(location['y'] + size['height']) * 1.25
  17.     )
  18.     # 打开当前页面截图
  19.     img_main = Image.open('./main.png')
  20.     # 抠出验证码图片
  21.     img_code = img_main.crop(img_tu)
  22.     # 保存验证码图片
  23.     img_code.save('code.png')
  24.     # 破解亚验证码
  25.     from chaojiying import ChaojiyingClient
  26.     chaojiying = ChaojiyingClient('zbh332525', '332525', '937257')
  27.     # chaojiying = ChaojiyingClient('用户名', '密码', '软件id')
  28.     im = open('code.png', 'rb').read()
  29.     code = chaojiying.PostPic(im, 1902)['pic_str']
  30.     return code
  31. browser = webdriver.Chrome()
  32. browser.implicitly_wait(5)
  33. browser.get('https://www.chaojiying.com/user/login/')
  34. browser.maximize_window()  # 浏览器全屏,免得有偏差
  35. # 写入用户名、密码、验证码
  36. username = browser.find_element(By.NAME, 'user').send_keys('zbh332525')
  37. password = browser.find_element(By.NAME, 'pass').send_keys('332525')
  38. code = browser.find_element(By.NAME, 'imgtxt').send_keys(get_code())
  39. time.sleep(2)
  40. # 登录按钮点击
  41. browser.find_element(By.XPATH, '/html/body/div[3]/div/div[3]/div[1]/form/p[4]/input').click()
  42. time.sleep(2)
  43. browser.quit()
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4