Spider--补充--selenium的使用
阅读原文时间:2023年07月11日阅读:1
# Selenium (firefox)

# 1,介绍:
# selenium 是一个 web 的自动化测试工具,是一个包,可以支持 C、 java、ruby、python、或都是 C# 语言。

# 1)安装:
# 1-1)安装 selenium
# pip install selenium  # 在 python中安装 selenium
# conda install -n data_analysis selenium  在 anaconda的虚拟环境中中安装 selenium  

# 1-2) 安装webdriver
# 各大浏览器webdriver地址可参见:https://docs.seleniumhq.org/download/
# Firefox:https://github.com/mozilla/geckodriver/releases/
# Chrome:https://sites.google.com/a/chromium.org/chromedriver/ 或者
# http://chromedriver.storage.googleapis.com/index.html
# IE:http://selenium-release.storage.googleapis.com/index.html
# 注:webdriver需要和对应的浏览器版本以及selenium版本对应

# 下载的压缩包文件名为:geckodriver-v0.26.0-win64.zip 解压之后得到 geckodriver.exe
# webdriver安装路径:
# Win:复制 geckodriver.exe 到Python/Anaconda安装目录下: C:\Users\XuYunPeng\anaconda3\
(复制geckodriver.exe(或chromedriver.exe)到任何已添加到 环境变量的文件夹)
# 如果上述配置设定好之后,执行代码后依然报错,代码修改如下:
# browser = webdriver.Firefox(executable_path=r"C:\Users\12078\Desktop\geckodriver-v0.25.0-win64\geckodriver.exe")   # executable_path=不要遗漏,关键字参数。

# 2,基本使用:
# 2-1)启动浏览器:
from selenium import webdriver
browser = webdriver.Firefox()  # browser = webdriver.Chrome() # browser = webdriver.Ie()
browser.get('http://www.baidu.com/')

# 2-2-1)设定 chorme无界面模式:
from selenium import webdriver

options = webdriver.ChromeOptions()     # chorme
options.add_argument('--headless')      # 设置无界面

browser=webdriver.Chorme(options=options)
browser.get('http://www.baidu.com/')

# 2-2-2)设定 firefox无界面模式:
from selenium import webdriver

options = webdriver.FirefoxOptions()    # firefox
options.add_argument('--headless')      # 设置无界面

browser=webdriver.Firefox(options=options)
browser.get('http://www.baidu.com/')

# 2-3)访问页面:
browser.get('http://www.renren.com/')
browser.maximize_window()  # 窗口最大化,可有可无,看情况
# browser.minimize_window()

# 2-4)定位元素并交互:
# 定位元素的方法:
# id定位:find_element_by_id()
# name定位:find_element_by_name()
# class定位:find_element_by_class_name()
# link定位:find_element_by_link_text()
# partial link定位:find_element_by_partial_link_text()
# tag定位:find_element_by_tag_name()
# xpath定位:find_element_by_xpath()
# css定位:find_element_by_css_selector()

# 以上是单元素的定位,多元素的定位把 element改为 elements即可。

# 通用方法:
# 将 By导入,使用 browser.find_element(By.ID,idname)  其中 browser=webdriver.Firefox()
from selenium import webdriver
from selenium.webdriver.common.by import By
browser = webdriver.Firefox()
browser.get('http://www.renren.com/')
input_first=browser.find_element(By.ID,'email')

# 元素定位的举例:

#coding=utf-8
from selenium import webdriver
browser=webdriver.Firefox()
browser.get("http://www.baidu.com")
# 百度输入框的定位方式:
# 通过id方式定位
browser.find_element_by_id("kw").send_keys("Collin")
# 通过name方式定位
browser.find_element_by_name("wd").send_keys("Collin")
# 通过tag name方式定位
browser.find_element_by_tag_name("input").send_keys("Collin")
# 通过class name方式定位
browser.find_element_by_class_name("s_ipt").send_keys("Collin")
# 通过CSS方式定位
browser.find_element_by_css_selector("#kw").send_keys("Collin")
# 通过xpath方式定位
browser.find_element_by_xpath("//input[@id='kw']").send_keys("Collin")
# 点击 搜索
browser.find_element_by_id("su").click()
time.sleep(3)  # 强制等待,后面再讲。
browser.quit()

# 3,鼠标事件:
# e.click()
# 除了可以使用 click( ) 来模拟鼠标的单击操作,现在Web产品中还提供了更丰富的鼠标交互方式,例如鼠标右键、双击、悬停、拖动等功能,
# 在WebDriver中,将这些关于鼠标操作的方法都封装在 ActionChains 类中。

# 4, 键盘事件
# 1) e.send_keys(要输入的值)
#  同样,操作键盘的几个方法也被封装进了 ActionChains 类中,如 actions.click(e).send_keys(要输入的值)

# 2),要想调用键盘按键操作,需要引入 keys 包:
from selenium.webdriver.common.keys import Keys   # 通过 send_keys()调用按键:
send_keys(Keys.TAB) # TAB
send_keys(Keys.ENTER) # 回车

# 鼠标事件一般包括鼠标右键、双击、拖动、移动鼠标到某个元素上等等。
# ActionChains方法列表:
# click(on_element=None) ——单击鼠标左键
# click_and_hold(on_element=None) ——点击鼠标左键,不松开
# context_click(on_element=None) ——点击鼠标右键
# double_click(on_element=None) ——双击鼠标左键
# drag_and_drop(source, target) ——拖拽到某个元素然后松开
# drag_and_drop_by_offset(source, xoffset, yoffset) ——拖拽到某个坐标然后松开
# key_down(value, element=None) ——按下某个键盘上的键
# key_up(value, element=None) ——松开某个键
# move_by_offset(xoffset, yoffset) ——鼠标从当前位置移动到某个坐标
# move_to_element(to_element) ——鼠标移动到某个元素
# move_to_element_with_offset(to_element, xoffset, yoffset) ——移动到距某个元素(左上角坐标)多少距离的位置
# perform() ——执行链中的所有动作
# release(on_element=None) ——在某个元素位置松开鼠标左键
# send_keys(*keys_to_send) ——发送某个键到当前焦点的元素
# send_keys_to_element(element, *keys_to_send) ——发送某个键到指定元素 

# ActionChains基本用法:
# 首先需要了解ActionChains的执行原理,当你调用ActionChains的方法时,不会立即执行,而是会将所有的操作按顺序存放在一个队列里,
# 当你调用perform()方法时,队列中的时间会依次执行。这种情况下我们可以有两种调用方法: 

# 链式写法
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu =  driver.find_element_by_css_selector(".nav #submenu1")

ActionChains(driver).move_to_element(menu).click(hidden_submenu).perform()

# 分步写法
menu = driver.find_element_by_css_selector(".nav")
hidden_submenu = driver.find_element_by_css_selector(".nav #submenu1")

actions = ActionChains(driver)

actions.move_to_element(menu)
actions.click(hidden_submenu)
actions.perform()

# 示例 1 菜鸟教程:
from selenium import webdriver
from selenium.webdriver import ActionChains

browser = webdriver.Firefox()
url = "http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable"
browser.get(url)
actions = ActionChains(browser)  # 将操作放入 actionchain中串行执行

browser.switch_to.frame('iframeResult')
source = browser.find_element_by_css_selector('#draggable')
target = browser.find_element_by_css_selector('#droppable')

actions.drag_and_drop(source, target)
actions.perform()

# 示例 2 登录人人网:
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver import ActionChains

browser = webdriver.Firefox(executable_path=r"C:\Users\12078\Desktop\geckodriver-v0.25.0-win64\geckodriver.exe")
# browser = webdriver.Firefox("C:/Users/12078/anaconda3/")
# browser = webdriver.Firefox("C:\Program Files\Mozilla Firefox")
# browser = webdriver.Chrome("C:\\Users\\12078\\anaconda3")
browser.get('http://www.renren.com/')
actions = ActionChains(browser)                                           # 获取 ActionChains 对象

with open("user_info.txt",'r') as f:
    user,pwd=f.read().strip().split('|')

# print(user)
# print(pwd)

browser.maximize_window()
# browser.find_element(By.ID,'email').clear()
# browser.find_element(By.ID,'email').send_keys(user)
# browser.find_element(By.ID,'password').send_keys(pwd)
# browser.find_element(By.ID,'login').click()  # 操作浏览器

email=browser.find_element(By.ID,'email')
email.clear()
actions.click(email).send_keys(user)                       # actions 预执行

psw=browser.find_element(By.ID,'password')
actions.click(psw).send_keys(pwd)                          # actions 预执行
submit=browser.find_element(By.ID,'login')
actions.click(submit)                                      # actions 预执行

actions.perform()                                          # actions 执行

# browser.close() # 关闭
# browser.quit()  # 退出

# 5,执行 js命令:
from selenium import webdriver
browser = webdriver.Chrome()
browser.get("http://www.zhihu.com/explore")

browser.execute_script('window.scrollTo(0, document.body.scrollHeight)')
browser.execute_script('alert("To Bottom")')

# 6, 输出和关闭浏览器:
from selenium import webdriver
browser = webdriver.Firefox()
browser.get("http://www.zhihu.com/explore")

print(browser.current_url)   # https://www.zhihu.com/explore
print(browser.page_source)   # JSON格式的数据
browser.close()
browser.quit()

# 7, frame标签:
# 很多网页中存在 frame 标签,要处理frame里面的数据,首先要切入frame,处理完了还要切出来。
# 切入 -- switch_to.frame(),
# 切出 -- switch_to.parent_frame().

# 示例:
# 在 id为 iframeResult的 frame里寻找 css_selector为'draggable' 及 class_name为 'logo'的元素
# 如果在 iframeResult里找不到 class_name为 'logo'的元素就退出 iframeResult,然后再寻找。

# encoding:utf-8
import time
from selenium import webdriver
from selenium.common.exceptions import NoSuchElementException

browser = webdriver.Firefox()
url = 'http://www.runoob.com/try/try.php?filename=jqueryui-api-droppable'
browser.get(url)
browser.switch_to.frame('iframeResult')     # 进入iframe  iframeResult 是 iframe 的 id
source = browser.find_element_by_css_selector('#draggable')
print(source)
try:
    logo = browser.find_element_by_class_name('logo')
except NoSuchElementException:
    print('NO LOGO')
browser.switch_to.parent_frame()           # 退出 iframe
logo = browser.find_element_by_class_name('logo')
print(logo)
print(logo.text)

# <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="cf33eb76-09fb-45c4-8c19-f4ca9df3df03", element="67784163-bf88-480e-99c5-1efa9ae4a94a")>
# NO LOGO
# <selenium.webdriver.firefox.webelement.FirefoxWebElement (session="cf33eb76-09fb-45c4-8c19-f4ca9df3df03", element="80aca415-4215-4207-aa85-d7816c145389")>
# RUNOOB.COM

# 8, 等待:

# 1) 强制等待:  time.sleep(10)
# 优点:简单明了.
# 缺点:不智能,可能会影响程序效率。

import time
time.sleep(10)

# 2) 隐式等待:  browser.implicitly_wait(100) 
# 优点:相比sleep() ,隐性更加智能,它会在你设置的时间内判断网页是否加载完成,如果完成了,就进行下一步;在设置的时间内没有加载完成,
# 则会报超时加载;
# 缺点:随着ajax技术的广泛应用,页面的元素往往都可以局部加载,也就是在整个页面没有加载完的时候,可能我们需要的元素已经加载完成了,
# 那就么有必要再等待整个页面的加载。

# 1.隐性等待的设置是全局性的,在开头设置过之后,整个的程序运行过程中都会有效,都会等待页面加载完成;不需要每次设置一遍;
# 2.页面加载完成后新打开的弹窗是没有等待效果的

from selenium import webdriver
browser = webdriver.Firefox()
browser.implicitly_wait(100)    # 等待整个页面加载完成
browser.get('https://www.zhihu.com/explore')
input = browser.find_element_by_class_name('zu-top-add-question')
print(input)

# 3)显式等待
# 举例:
# input= WebDriverWait(browser, 100).until(EC.presence_of_element_located((By.ID, 'q'))) # 最长等待100秒,直到 id为 'q'的元素出现
# button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))  # 最长等待100秒,直到按钮可以点击。

# WebDriverWait(browser, 100).until_not(EC.presence_of_element_located((By.ID, 'q')))  #最长等待100秒,直到 id为 'q'的元素消失
# button = wait.until_not(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))  #最长等待100秒,直到按钮不可以点击。

# 示例 1:
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

browser = webdriver.Firefox()
browser.get('https://www.taobao.com/')
wait = WebDriverWait(browser, 100)    #
input = wait.until(EC.presence_of_element_located((By.ID, 'q')))
button = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, '.btn-search')))
print(input, button)

# 示例 2:
from datetime import datetime
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

driver = webdriver.Chrome()
driver.get("http://www.baidu.com")
driver.maximize_window()
try:
    print(datetime.now())  #
    element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID, "kw")))

    print(datetime.now())
    element = WebDriverWait(driver,10).until(EC.presence_of_element_located((By.ID, "kw111")))

finally:
    print(datetime.now())
    driver.quit()

# 注意:最好对于元素选择全部独立封装成方法,在每个方法中可以加上日志、显示等待
# 对于 until()和 until_not()使用的布尔参数还有:
# title_is:判断当前页面的title是否等于预期
# title_contains:判断当前页面的title是否包含预期字符串
# presence_of_element_located:判断某个元素是否被加到了dom树里,并不代表该元素一定可见
# visibility_of_element_located:判断某个元素是否可见. 可见代表元素非隐藏,并且元素的宽和高都不等于0
# visibility_of:跟上面的方法做一样的事情,只是上面的方法要传入locator,这个方法直接传定位到的element就好了
# presence_of_all_elements_located:判断是否至少有1个元素存在于dom树中。举个例子,如果页面上有n个元素的class都是'column-md-3',那么只要有1个元素存在,这个方法就返回True
# text_to_be_present_in_element:判断某个元素中的text是否 包含 了预期的字符串
# text_to_be_present_in_element_value:判断某个元素中的value属性是否包含了预期的字符串
# frame_to_be_available_and_switch_to_it:判断该frame是否可以switch进去,如果可以的话,返回True并且switch进去,否则返回False
# invisibility_of_element_located:判断某个元素中是否不存在于dom树或不可见
# element_to_be_clickable - it is Displayed and Enabled:判断某个元素中是否可见并且是enable的,这样的话才叫clickable
# staleness_of:等某个元素从dom树中移除,注意,这个方法也是返回True或False
# element_to_be_selected:判断某个元素是否被选中了,一般用在下拉列表
# element_located_to_be_selected
# element_selection_state_to_be:判断某个元素的选中状态是否符合预期
# element_located_selection_state_to_be:跟上面的方法作用一样,只是上面的方法传入定位到的element,而这个方法传入locator
# alert_is_present:判断页面上是否存在alert

# 10, 控制浏览器的前进和后退:
import time
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.baidu.com/')
browser.get('https://www.taobao.com/')
browser.back()
time.sleep(1)
browser.forward()
# browser.close()

# 11, cookie 操作
get_cookies()
delete_all_cookies()
add_cookie()

# 示例:
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.zhihu.com/explore')
print(browser.get_cookies())
browser.add_cookie({'name': 'name', 'domain': 'www.zhihu.com', 'value': 'hahah'})
print(browser.get_cookies())
browser.delete_all_cookies()
print(browser.get_cookies())

# 12, 选项卡管理:
# 通过执行js命令实现新开选项卡 window.open(),所有选项卡都存在列表 browser.window_handles 里,
# 通过 browser.window_handles[0]就可以操作第一个选项卡。

import time
from selenium import webdriver

browser = webdriver.Firefox()
browser.get('https://www.baidu.com')
browser.execute_script('window.open()')  # 用 js 实现新开选项卡
print(browser.window_handles)
browser.switch_to_window(browser.window_handles[1])  # 切换选项卡
browser.get('https://www.taobao.com')
time.sleep(1)
browser.switch_to_window(browser.window_handles[0]) # 切换选项卡
browser.get('https://python.org')

# 13, 异常处理:
# 这里的异常比较复杂,官网的参考地址: http://selenium-python.readthedocs.io/api.html#module-selenium.common.exceptions
# 现用现查,这里只进行简单的演示,查找一个不存在的元素:

# 示例:
from selenium import webdriver
from selenium.common.exceptions import TimeoutException, NoSuchElementException

browser = webdriver.Chrome()
try:
    browser.get('https://www.baidu.com')
except TimeoutException:
    print('Time Out')
try:
    browser.find_element_by_id('hello')
except NoSuchElementException:
    print('No Element')
finally:
    browser.close()

# 14,设置代理和请求头:
https://blog.csdn.net/xc_zhou/article/details/80823855

# 示例:
import requests
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def gettop250():
    move_list=[]
    url='https://movie.douban.com/top250?start='
    # 设置 headers
    user_agent='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36',
    dcap = dict(DesiredCapabilities.FIREFOX)
    dcap["phantomjs.page.settings.userAgent"] = user_agent
    options = webdriver.FirefoxOptions()
    # 设置无界面
    options.add_argument('--headless')
    driver=webdriver.Firefox(executable_path=r"C:\Users\12078\Desktop\geckodriver-v0.25.0-win64\geckodriver.exe",options=options)

    for i in range(10):
        driver.get(url+str(i*25)+"&filter=")
        movelist=driver.find_elements_by_class_name('hd')
        for move in movelist:
            move_list.append(move.find_element_by_class_name('title').text.strip())  # 第一个 title(即中文)
    return move_list

print(gettop250())


参考:
https://www.cnblogs.com/yanshw/p/10852860.html
https://www.cnblogs.com/zhaof/p/6953241.html