您现在的位置是:网站首页 > 博客日记 >

python|爬虫|自动化|selenium语法|cookie操作|执行js|无头|获取资源链接|自动安装|防检测

作者:YXN-python 阅读量:89 发布日期:2024-05-15

安装

# 文档: https://selenium-python-zh.readthedocs.io/en/latest/
# 需要安装 : pip install urllib3==1.26.2 selenium==3.141.0 
# pip install urllib3==1.26.2

配置

参考:selenium驱动配置|chromedriver|Edge WebDriver

使用

导入

from selenium import webdriver

1、打开浏览器

# 用代码打开浏览器
driver = webdriver.Chrome()  # Chrome 的 C 大写

# driver 就是那个打开的浏览器 对象,浏览器不要关闭

2、打开网址

driver.get('https://www.baidu.com/')

3、查找网页标签对象

    查找单个对象 , 返回 xxx 范围内的第一个
    xxx.find_element_by_id( id的值 )			   # id定位
    xxx.find_element_by_tag_name( 标签名称 )	  # 标签定位
    xxx.find_element_by_name('wd')				 # name定位
	xxx.find_element_by_class_name( class的值 )	# class定位
    xxx.find_element_by_link_text('新闻')	   		# 完整超链接定位(a标签)
    xxx.find_element_by_partial_link_text('新')	 # 部分链接定位(a标签)
    xxx.find_element_by_css_selector('.s_ipt')	  # CSS定位
    xxx.find_element_by_xpath("//*[@name='wd']")  # XPath定位
    
    查找多个对象,返回列表
    xxx.find_elements_by_tag_name( 标签名称 )
    xxx.find_elements_by_class_name( class的值 )

# 找到输入框
shuru = driver.find_element_by_id('kw')
shuru

4、向输入框输入文本

xxx.send_keys( 文本 )
xxx.clear( ) 清空
shuru.send_keys('明天')

# 也可上传文件
# filepath填写真实的文件路径
XXX.find_element_by_name("UploadFile").send_keys("filepath")

5、点击的语法

from selenium import webdriver
from selenium.webdriver import ActionChains

xxx.click() # 模拟鼠标单击操作
driver.find_element_by_id('su').click()

driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
element = driver.find_element_by_link_text(u"新闻")#u:utf-8默认在string前面加u,可不加

#鼠标右击
ActionChains(driver).context_click(element).perform()
#鼠标双击
ActionChains(driver).double_click(element).perform()
  • click_and_hold():单击且按住不放
  • double_click():双击
  • context_click():右击
  • drag_and_drop(source,target):拖曳
  • drag_and_drop(source,xoffset,yoffset):将鼠标拖曳到目标位置
  • key_down():按住某个键,实现快捷键操作
  • key_up():松开某个键,一般和key_down操作一起使用
  • move_to_element():鼠标悬停
  • move_to_element_with_offset(to_element,xoffset,yoffset):鼠标悬停至指定的坐标
  • perform():将之前一系列的ActionsChains执行
  • release():释放按下的鼠标

6、滚动页面

xxx浏览器对象.execute_script('window.scrollBy(x,y)')
    x,y 可正可负
    x 是左右滚动
    y 是上下滚动

# 向下滚500
driver.execute_script('window.scrollBy(0,500)')

# 往右滚50
driver.execute_script('window.scrollBy(50,0)')

# 模拟匀速滚
import time
for i in range(50):
    time.sleep(0.02)
    driver.execute_script('window.scrollBy(0,20)')

# 随机时长,随机距离
import random
for i in range(5):
    time.sleep( random.uniform(0.5,1.5) )
    height = random.randint(200,600)
    driver.execute_script(f'window.scrollBy(0,{height})')

7、获取文本和属性

xxx.text
xxx.get_attribute('属性名称')  得到属性的值

# 找出 id=1 的 标签 内部 的 第一个 a标签
# 百度首页的 id=1 两个

driver.find_elements_by_id('2')[0].find_element_by_tag_name('a').text

driver.find_elements_by_id('1')[1].find_element_by_tag_name('a').text

driver.find_elements_by_id('1')[1].find_element_by_tag_name('a').get_attribute('href')

#  直接找搜索结果的id=2,先找父层

driver.find_element_by_id('content_left').find_element_by_id('2').find_element_by_tag_name('a').text

xpath 的方式 取标签

find_element_by_xpath
     就像文件夹路径一样使用
 /  从根节点开始取内容  , 根节点是 html ,
     不能跳层级,只能一层一层往下写
 // 从根节点开始,但是可以跨节点
 .  当前节点
 ..  父节点
 @ 属性
    查找 <div id='abc' class="xyz">内容</div>

    //div[@id="abc"]
    //div[@id="abc"][@class="xyz"]

driver.find_element_by_xpath('//div[@id="content_left"]/div[@id="2"]//a').text

8、最大最小化窗口 ,以及其他窗口处理

driver.maximize_window()  最大化
driver.minimize_window()   最小化
driver.set_window_size(宽度,高度)   指定大小
driver.set_window_position(距离左边,距离上面)  设置位置

driver.get_window_size() 获取大小
driver.get_window_position() 获取位置

driver.forward() 前进
driver.back() 后退

# 向下滚500
driver.execute_script('window.scrollBy(0,500)')

9、窗口句柄

每打开一个 Tab 标签页就会多一个窗口句柄
代码控制浏览器,必须通过代码切换窗口,才可以控制对应的窗口

如何打开一个新的标签页
  driver.execute_script('window.open("url")')
	或者
    img_page = 'https://fanyi.baidu.com/#en/zh/'
    new_window='window.open("{}")'.format(img_page)
    driver.execute_script(new_window)

如何获取窗口句柄
  driver.window_handles  返回list
  点击式的新窗口按照时间顺序追加进来的

# 比如 打开网易云音乐

driver.execute_script('window.open("https://music.163.com/")')
driver.window_handles

窗口句柄默认还是在之前的窗口中,它不像我们实际的操作点击就换到新界面了,代码操作需要用代码命令的方式去切换窗口,才能实现代码控制对应的窗口。 
关闭了一个窗口后,需要切回到某个窗口才能继续操作
切换窗口
driver.switch_to.window( 具体的句柄对象 )

具体的句柄对象通过 下标读取 
driver.window_handles[index]
driver.switch_to.window(driver.window_handles[0])
driver.switch_to.window(driver.window_handles[2])
driver.execute_script('window.scrollBy(0,500)')

# 切换到 网易云的窗口上

driver.switch_to.window(driver.window_handles[1])
driver.execute_script('window.scrollBy(0,500)')

# 又滚不动了, 为什么?

10、切换网页框架

网页标签可以通过 iframe 标签实现  页中页

如果需要控制的或者内容在 iframe 中,需要切换iframe
    driver.switch_to.frame( iframe对象 )

iframe对象怎么来?:
    1、iframe的id
    2、iframe的name(不写)
    3、 通过  find_element... 的方法得到的对象

回到默认层级:
   driver.switch_to.default_content( ) 

# 切换到内层iframe

driver.switch_to.frame('g_iframe')
driver.execute_script('window.scrollBy(0,500)')

# 手动开一个新窗口,进入飙升榜

driver.switch_to.window(driver.window_handles[3])
driver.execute_script('window.scrollBy(0,500)')
iframe = driver.find_element_by_id('g_iframe')
iframe
driver.switch_to.frame(iframe)
driver.execute_script('window.scrollBy(0,500)')

11、刷新页面

driver.refresh()

12、关闭当前代码所在的窗口句柄

driver.close()
注意:如果需要使用其他窗口,需要切换过去
driver.close()
driver.switch_to.window(driver.window_handles[0])

13、键盘事件

  • Keys.BACK_SPACE:删除键
  • Keys.SPACE:空格键
  • Keys.TAB:Tab键
  • Keys.ESCAPE:回退键
  • Keys.ENTER:回车键
  • Keys.CONTROL,“a”:组合键 Ctrl + A
  • Keys.CONTROL,“x”:组合键 Ctrl + X
  • Keys.CONTROL,“v”:组合键 Ctrl + V
  • Keys.CONTROL,“c”:组合键 Ctrl + C
  • Keys.F1:F1键
  • Keys.F12:F12键
有的时候  xxx.click()失效 , 就可以触发回车代替点击
需要导入键盘的类

xxx.send_keys(  )

# 最后 的 Keys ,K 要大写
from selenium.webdriver.common.keys import Keys

# 可以通过 输入 Keys.  按 Tab 键提示,看看有哪些
shuru = driver.find_element_by_xpath('//input[@id="kw"]')
shuru.send_keys( Keys.BACK_SPACE )
shuru.send_keys( Keys.NUMPAD3 )
shuru.send_keys( '456' )

# 组合键 ctrl + a
shuru.send_keys( Keys.CONTROL ,'a' )

# 回车
shuru.send_keys(Keys.ENTER)

14、获取网页解析后的页面代码

得到一个str
driver.page_source  

selenium提取网页内容效率低,
而用解析后的代码, 就可以转为 bs4 对象 ,再用bs4的知识提取内容,效率高。
driver.page_source

15、完全退出浏览器

driver.quit()
driver.quit()
# 更多时候 是 手动 + 代码 结合

16、判断网页是否加载完成

更多->条件判断

三种等待方法:
1.强制等待sleep(xx)
强制等待,不管你浏览器是否加载完了,程序都得等待,时间一到,继续执行下面的代码,作为调试很有用,有时候也可以在代码里这样等待,不过不建议总用这种等待方式,太死板,严重影响程序执行速度。

2.隐性等待implicitly_wait(xx)
隐形等待是设置了一个最长等待时间,如果在规定时间内网页加载完成,则执行下一步,否则一直等到时间截止,然后执行下一步。有些时候我们不需要等到所有元素加载完成,我想等我要的元素出来之后就立马执行下一步,那就应该用显性等待。
driver.implicitly_wait(10) # 隐性等待10秒

3.显性等待WebDriverWait(driver,timeout,xx),配合该类的until()和until_not()方法
程序每隔xx秒看一眼,如果条件成立了,则执行下一步,否则继续等待,直到超过设置的最长时间,然后抛出TimeoutException。

17、webdriver对象常用操作(小结)

  • 访问url - get()
  • 本机上没有浏览器,需要远程调用浏览器进行自动化测试 -- remote WebDriver
  • 调整浏览器窗口大小
  • 后退 - back()
  • 前进 - forward()
  • 刷新 - refresh()
  • 提交 - submit()
  • 退出驱动关闭所有窗口 - quit()
  • 关闭当前窗口 - close()
  • 获取当前窗口的url - current_url
  • 获取当前所在窗口句柄 - current_window_handle
  • 获取所有窗口句柄 - current_window_handle
  • 切换浏览器窗口 - switch_to_window(handle)
  • 切换frame - switch_to_frame(frame_reference)
  • 获取元素坐标 - location
  • 获取元素的tag_name - tag_name
  • 获取浏览器名字 - driver.name
  • 返回当前页面的标题 - title
  • 清空输入框内容 - clear()
  • 截屏当前页面 - get_screenshot_as_file(filename)
  • 获取当前窗口的坐标 - get_window_position()
  • 获取当前窗口的宽高 - get_window_position()
  • 获取当前窗口的宽高和坐标 - get_window_rect()
  • is_selected():判断元素是否被选中,多用于选择框
  • is_enabled():判断页面元素是否可用
  • is_displayed():判断元素在页面是否显示

18、JavaScript操作页面元素

即执行 js 代码

#js用法
js = "document.getElementById('kw').value = 'selenium'"
driver.execute_script(js)

#设置浏览器窗口大小,目的是让滚动条显示出来
driver.set_window_size(800,700)
driver.find_element_by_id('kw').send_keys("selenium")
driver.find_element_by_id('su').click()
js = "window.scrollTo(100,300)"
#js = "window.scrollTo(0,document.body.scrolllHeight)"#滚动条滑到底部,未实现
driver.execute_script(js)

19、Cookie操作

add_cookie():在当前会话中添加Cookie信息,并且参数是属于字典类型数据

delect_all_cookie():删除所有的Cookie信息

delete_cookie(cookie_name):删除单个名字为“cookie_name”的Cookie信息

get_cookie(cookie_name):返回名为“cookie_name”的Cookie信息

get_cookies():返回当前会话的所有Cookie信息

delete_all_cookies() :清理浏览器所有coolie

20、无头浏览器

from selenium import webdriver

chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument('--headless')
driver = webdriver.Chrome(options=chrome_options)

21、获取浏览器资源链接

# 获取浏览器网页资源 返回文件 路径 的 列表
def get_file_url(browser_drive, **args):
    """
    xpath: 等待xpath表达式元素内容加载完成,与ID二选一
    ID: 等待id为ID 元素内容加载完成
    start:定义所需资源的头部
    end:定义所需资源的尾部
    """
    import time
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as ec
    # 显示等待
    if args.get('xpath'):
        try:
            WebDriverWait(driver, 10).until(lambda x: x.find_element(By.XPATH, args.get('xpath')))
        except Exception as e:
            print(e)
            return e
    elif args.get('ID'):
        WebDriverWait(driver, 10).until(ec.presence_of_element_located((By.ID, args.get('ID'))))
    else:
        time.sleep(2)
    # 获取所有加载的资源
    resources = browser_drive.execute_cdp_cmd('Page.getResourceTree', {})
    file_list = []
    # 遍历每个资源路径
    for resource in resources['frameTree']['resources']:
        if args.get('start') is not None and args.get('end') is not None:
            if resource['url'].startswith(args.get('start')) and resource['url'].endswith(args.get('end')):  # 筛选 特定 开头及结尾地址
                file_list.append(resource['url'])
                continue
        elif args.get('start') is None and args.get('end') is None:
            file_list.append(resource['url'])
            continue
        else:
            if args.get('start') is not None:
                if resource['url'].startswith(args.get('start')):
                    file_list.append(resource['url'])
                    continue
            if args.get('end') is not None:
                if resource['url'].endswith(args.get('end')):
                    file_list.append(resource['url'])
                    continue

    return file_list

# 等待id为captcha的元素加载完成后,获取本地域名下的 css文件
get_file_url(driver, start='http://127.0.0.1/', end='css', ID='captcha')

22、自动安装浏览器

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from webdriver_manager.chrome import ChromeDriverManager
browser = webdriver.Chrome(ChromeDriverManager().install())
browser.get('https://www.baidu.com')

23、防止浏览器检测到自动化操作

# 在Chrome当中添加实验性功能参数
from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions

option = ChromeOptions()
option.add_experimental_option('excludeSwitches',['enable-automation'])
driver=Chrome(options=option)


# 调用chrome当中的开发工具协议的命令
driver = webdriver.Chrome()
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                       {"source": """
                           Object.defineProperty(navigator, 'webdriver', {
                             get: () => undefined
                           })
                         """})

# 二者结合
from selenium import webdriver
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-automation"])
options.add_experimental_option('useAutomationExtension', False)
driver = webdriver.Chrome(options=options, executable_path='./chromedriver')
driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
  "source": """
    Object.defineProperty(navigator, 'webdriver', {
      get: () => undefined
    })
  """
})
driver.get(url)

也可以通过运行`stealth.min.js`文件来实现隐藏`selenium`模拟浏览器的特征,这个文件之前是给`puppeteer`用的,使得其隐藏浏览器的指纹特征,而让`Python`使用时,需要先导入这份`JS`文件

import time
from selenium.webdriver import Chrome

option = webdriver.ChromeOptions()
option.add_argument("--headless")

# 无头浏览器需要添加user-agent来隐藏特征
option.add_argument('user-agent=.....')
driver = Chrome(options=option)
driver.implicitly_wait(5)

with open('stealth.min.js') as f:
    js = f.read()

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
  "source": js
})

driver.get(url)

24、随机睡眠

import random
time.sleep( random.uniform(0.5,1.5) )

YXN-python

2024-05-15