0


爬虫 — 自动化爬虫 Selenium

目录

一、介绍

Selenium 爬取网页时,当前访问的 url 就是爬虫当中的目标 url,获取内容只要是页面上可见的,都可以爬取(可见即可爬)。

步骤

Selenium + 浏览器 + 浏览器驱动

1、导入

2、url(找动态 url,抓取到的数据是加密的)

3、获取内容,做解析

Selenium 是一个用于 Web 应用程序测试的工具,最初是为网站自动化测试而开发的,Selenium 可以直接运行在浏览器上,它支持所有主流的浏览器,可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏。

chromedriver 是一个驱动 Chrome 浏览器的驱动程序,使用它才可以驱动浏览器。

针对不同的浏览器有不同的 driver,但 Chrome 的兼容性最好。

二、对比

Ajax:可以使用网页实现异步更新,可以在不重新加载整个网页的情况下,对网页的某部分进行更新。

1、获取 Ajax 数据的方式

  • 直接分析 Ajax 调用的接口,然后通过代码请求这个接口。
  • 使用 Selenium + chromedriver 模拟浏览器行为获取数据。

2、获取 Ajax 数据方式对比
方式优点缺点找数据接口直接可以请求到数据,代码量少,性能高分析接口比较复杂,尤其通过 js 混淆的接口,容易被发现是爬虫Selenium直接模拟浏览器行为,浏览器能请求到的,使用 Selenium 也能请求到代码量多,性能低

三、安装

1、驱动下载地址

下载 Chrome 驱动

下载 Firefox 驱动

2、安装 Selenium 第三方库(建议指定版本安装)

pip install selenium==4.0.0a1

3、安装驱动(Chrome 的兼容性最好,建议安装 chromedriver)

  • 先确定浏览器版本号

在这里插入图片描述

在这里插入图片描述

  • 打开谷歌驱动下载地址

在这里插入图片描述

  • 版本号前面三位对应上就可以,最后一位建议选择版本小的

在这里插入图片描述

  • 按照电脑的系统来选择下载(如果电脑是 windows-64 位,选 win32 就行)

在这里插入图片描述

  • 驱动下载完成之后,将文件进行解压,复制到 chromedriver.exe 到 Python 解释器目录下

终端输入命令:where python 可以查看 Python 的安装目录

四、简单使用

# 导入模块,加载驱动from selenium import webdriver
# 内置库import time

# 加载驱动
drive = webdriver.Chrome()# 窗口最大化
drive.maximize_window()# 加载网站
drive.get('https://www.baidu.com')# 代码停3秒再运行
time.sleep(3)# 关闭当前的窗口# drive.close()  # 要打开多个窗口,关闭的是当前的窗口# 退出驱动
drive.quit()# 关闭所有窗口,退出浏览器

五、定位元素

# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 窗口最大化
driver.maximize_window()# 加载网站
driver.get('https://www.baidu.com')

1、By.ID

根据 id 来查找定位元素。

# find_element 找一个元素,find_elements 找多个
el = driver.find_element(By.ID,'kw')# 返回的是一个元素对象print(el)

2、By.CLASS_NAME

通过 class 属性值定位某个元素。

el = driver.find_element(By.CLASS_NAME,'s_ipt')# 返回的是一个元素对象print(el)

3、By.NAME

通过 name 属性查找定位某个元素。

el = driver.find_element(By.NAME,'wd')# 返回的是一个元素对象print(el)

4、By.TAG_NAM

通过标签定位元素。

input_tag = driver.find_elements(By.TAG_NAME,'input')# find_elements 定位元素,返回的数据类型是 listprint(input_tag)

5、By.XPATH

通过 xpath 语法定位元素。

el = driver.find_element(By.XPATH,'//input[@id="kw"]')# 返回的是一个元素对象print(el)

六、操作元素

1、在输入框输入内容并搜索

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 窗口最大化
driver.maximize_window()# 加载网站
driver.get('https://www.baidu.com')# 定位到元素
el = driver.find_element(By.ID,'kw')# 元素输入框里面输入值
el.send_keys('唐僧')# 等待2秒
time.sleep(2)# 点击元素
driver.find_element(By.ID,'su').click()# 清空内容
el.clear()

2、打开网站搜索音乐并播放

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By
# 操作键盘from selenium.webdriver.common.keys import Keys

# 加载驱动
driver = webdriver.Chrome()# 窗口最大化
driver.maximize_window()# 加载网站
driver.get('https://music.163.com/')# 搜索内容
driver.find_element(By.ID,'srch').send_keys('愿')# 按回车键
driver.find_element(By.ID,'srch').send_keys(Keys.ENTER)# 等待2秒
time.sleep(2)# 网页里面嵌套了一个网页,要进入该网页才会获取对应的数据
driver.switch_to.frame('g_iframe')# 播放按钮
driver.find_element(By.ID,'song_2010214999').click()

七、Cookie 操作

1、获取所有的 Cookie

cookies = driver.get_cookies()

2、根据 Cookie 的 name 获取 Cookie

value = driver.get_cookie(name)

3、删除某个 Cookie

driver.delete_cookie('key')

4、处理 Cookie

# 导入模块,加载驱动from selenium import webdriver

# 加载驱动
driver = webdriver.Chrome()# 窗口最大化
driver.maximize_window()# 加载网站
driver.get('https://www.baidu.com')# 获取百度的 cookie
cookies = driver.get_cookies()# 返回的 list,列表里面嵌套的字典print(cookies)'''
通过程序拿到的 cookie 与页面的是不一致,还需要做处理
只需要里面的两个字段值,name 和 value
BAIDUID_BFESS=F875E52E04E65B3748D8FDDE2E25399E; ZFY=idY6KuND2T0e6ROY1txjofI8Nvn4lb6hXiw:BN2mgeaA:C
'''for cookie in cookies:print(cookie['name']+'='+ cookie['value'])

5、案例

模拟登录 qq 空间

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://i.qq.com/')# 切换 iframe
driver.switch_to.frame('login_frame')# 等待2秒
time.sleep(2)# 点击头像进行登录,获取登录之后的 cookie
driver.find_element(By.ID,'img_out_1234567890').click()# 等待2秒
time.sleep(2)# 获取 cookie
cookies = driver.get_cookies()# 打印出的数据为列表# print(cookies)# 获取的 cookie 需要处理
li =[]for cookie in cookies:# 只需要每一组字典里面的 name value
    li.append(cookie['name']+'='+cookie['value'])# print(cookie)# 处理好的 cookie
cookie ='; '.join(li)print(cookie)# 导入库import requests

# 确定 url, 静态加载的
url ='https://user.qzone.qq.com/1234567890'# 设置请求头参数
head ={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36','cookie': cookie
}# 发请求,获取响应
res = requests.get(url, headers=head)# 获取响应内容# print(res.text)# 写入文件withopen('qq.html','w', encoding='utf-8')as f:
    f.write(res.text)

八、Selenium 操作下拉菜单

select 元素不能直接点击,因为点击后还需要选中元素,这时候 selenium 就专门为 select 标签提供了一个类。

from selenium.webdriver.support.ui import Select

将获取到的元素当成参数传到这个类中,创建这个对象后,就可以使用这个对象进行选择了。

案例

目标网站:https://news.sina.com.cn/

需求:选择娱乐版块,日期8号相关新闻

分析:

1、打开对应网站

2、点击下拉菜单,选择对应的版块内容

3、点击日期图标,选择的日期是8号

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 专门针对 Select 标签使用from selenium.webdriver.support.ui import Select
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://news.sina.com.cn/')# 解析,直接定位到 select 标签
el = driver.find_element(By.NAME,'channel')# print(el)# 定位到娱乐的板块,实例化 select 对象
select_tag = Select(el)# 定位下拉框# 方法一# select_tag.select_by_index(4)  # 下标从0开始的# 方法二# select_tag.select_by_value('ent')  # 根据 option 里面 value 属性定位的# 方法三
select_tag.select_by_visible_text('娱乐')# text 指的是文本# 等待1秒
time.sleep(1)# 定位日期
driver.find_element(By.NAME,'date').click()# 选择8号
driver.find_element(By.XPATH,'//div[@id="dataView"]/div/table/tbody/tr[2]/td[2]').click()

九、Selenium 鼠标行为链

页面中需要借助鼠标操作元素,那么这时候可以使用鼠标行为链类 ActionChains 来完成,比如现在要将鼠标移动到某个元素上并执行点击事件。

学习文档

1、常用方法

actions = ActionChains(driver)# 实例化⼀个⿏标⾏为链的对象
actions.move_to_element(inputTag)# 将⿏标移动到元素的中间
actions.send_keys_to_element(inputTag,'python')# 将键发送到元素
actions.move_to_element(submitTag)# 将⿏标移动到元素的中间
actions.context_click()# 对元素执⾏上下⽂单击(右键单击)
actions.click(submitTag)# 单击⼀个元素
actions.perform()# 执⾏所有存储的操作
actions.lick_and_hold(element)# 点击但不松开⿏标
actions.double_click(element)# 双击

更多方法可参考

2、案例

目标网站:https://passport.vip.com/login?src=https%3A%2F%2Fwww.vip.com%2F

需求:

1、加载网站

2、切换登录方式

3、输入账号密码,勾选协议,点击登录案例

4、鼠标移动到对应的验证码元素上面

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By
# 导入鼠标行为链from selenium.webdriver import ActionChains

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://passport.vip.com/login?src=https%3A%2F%2Fwww.vip.com%2F')# 等待2秒
time.sleep(2)# 切换登录方式 —— 1、定位元素 2、点击
driver.find_element(By.XPATH,'//div[@class="c-tab-nav "]/div[2]').click()# 等待0.5秒
time.sleep(0.5)# 输入用户名
driver.find_element(By.ID,'J_login_name').send_keys('3424234234')# 输入密码
driver.find_element(By.ID,'J_login_pwd').send_keys('34234242')# 等待0.5秒
time.sleep(0.5)# 勾选协议
inputs = driver.find_element(By.ID,'J_login_agree')# 定位到这个元素# 通过 click 无法点击成功,可以采用 js 点击
driver.execute_script('arguments[0].click();', inputs)# 登录
driver.find_element(By.ID,'J_login_submit').click()# 等待1秒
time.sleep(1)# 定位图片
img = driver.find_element(By.CLASS_NAME,'vipsc_qimg')# 鼠标移动
actions = ActionChains(driver)
actions.move_to_element(img)# 移动到目标位置# 提交行为链
actions.perform()

十、Selenium 切换页面与操作多窗口

1、切换页面

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 先模拟打开多个网站
driver.get('https://www.baidu.com')# 百度
time.sleep(3)
driver.execute_script('window.open("https://www.douban.com/")')# 豆瓣
time.sleep(3)
driver.execute_script('window.open("https://juejin.cn/")')# 掘金
time.sleep(3)
driver.execute_script('window.open("https://cloud.tencent.com/developer/ask/sof/1237007")')# 腾讯
time.sleep(3)# 打印鼠标聚焦的 url# print(driver.current_url)# 切换窗口
driver.switch_to.window(driver.window_handles[-3])'''
0:https://www.baidu.com
1:https://cloud.tencent.com/developer/ask/sof/1237007
2:https://juejin.cn/
3:https://www.douban.com/

-1:https://www.douban.com/
-2:https://juejin.cn/
-3:https://cloud.tencent.com/developer/ask/sof/1237007
'''# 打印鼠标聚焦的 urlprint(driver.current_url)

2、多窗口操作

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://juejin.cn/')# 等待2秒
time.sleep(2)# 定位第二篇文章
driver.find_element(By.XPATH,'//div[@class="entry-list list"]/li[2]').click()# 等待1秒
time.sleep(1)# 切换窗口
driver.switch_to.window(driver.window_handles[1])# 获取 elements 内容
te = driver.page_source
print(te)

十一、Selenium 高级操作

1、page_source:返回结构的源码

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://music.163.com/#/discover/toplist')# 等待2秒
time.sleep(2)# 切换到 iframe
driver.switch_to.frame('g_iframe')# 等待2秒
time.sleep(2)# 拿到的是 elements 里面的内容,xpath 直接做解析就可以了print(driver.page_source)

2、find():在源码当中查找某个字符的存在

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://tieba.baidu.com/f?kw=%E8%8F%9C%E8%B0%B1&ie=utf-8&pn=11400')# 等待2秒
time.sleep(2)# # 获取网页源码# html = driver.page_source# # 打印源码# print(html)# # 看网页源码里是否存在下一页# print(driver.page_source.find('下一页>'))'''
如果没有查找到对应的字符,返回的是-1
如果查找到了,返回的是数字
'''whileTrue:# 判断源码里存在下一页时if driver.page_source.find('下一页>')!=-1:# 点击下一页的按钮
        driver.find_element(By.CLASS_NAME,'next').click()# 等待1秒
        time.sleep(1)# 源码里不存在下一页时,跳出循环else:print('已经是最后一页了')break

3、By.LINK_TEXT:根据链接文本定位

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://movie.douban.com/top250')# 等待2秒
time.sleep(2)# 获取网页源码
html = driver.page_source

# 等待1秒
time.sleep(1)# 根据链接文本定位,点击‘后页>’
driver.find_element(By.LINK_TEXT,'后页>').click()# 打印点击‘后页>’后的文本print(driver.page_source)

4、get_attribute():获取属性值

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://movie.douban.com/top250')# 等待2秒
time.sleep(2)# 获取图片标签
img_tag = driver.find_element(By.XPATH,'//div[@class="pic"]/a/img')# 获取属性值 —— 通过方法print(img_tag.get_attribute('src'))

5、.text:获取节点内容

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 最大化窗口
driver.maximize_window()# 加载网站
driver.get('https://movie.douban.com/top250')# 等待2秒
time.sleep(2)# 获取文本内容
div_tag = driver.find_element(By.XPATH,'//div[@class="hd"]').text

# 打印文本内容print(div_tag)

十二、设置无界面

# 内置库import time
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 设置参数
options = webdriver.ChromeOptions()# 设置无界面模式
options.add_argument('--headless')# 传递参数
driver = webdriver.Chrome(options=options)# 加载网站
driver.get('https://movie.douban.com/top250')# 等待3秒
time.sleep(3)# 获取图片标签
img_tag = driver.find_element(By.XPATH,'//div[@class="pic"]/a/img')# 打印属性值print(img_tag.get_attribute('src'))

十三、页面等待

1、强制等待

time.sleep(时间)

2、隐式等待

调用 driver.implicitly_wait ,针对所有元素,设置等待时间,如果等待时间内加载出来,代码继续往下走,等待时间以内不断刷新看元素是否加载出来,超出则报出异常。

# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 加载驱动
driver = webdriver.Chrome()# 加载网站
driver.get('https://www.baidu.com')# 显示等待,针对的全局元素
driver.implicitly_wait(10)# 10秒内出现代码继续往下走
driver.find_element(By.ID,'kw').send_keys('python')# 等待10秒不出现就会报错
driver.find_element(By.ID,'kw1').send_keys('python')

3、显示等待

表明某个条件成立后才执行获取元素的操作,也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。

# 显示等待,需要导入模块# 导入 WebDriverWait 类from selenium.webdriver.support.wait import WebDriverWait
# 导入 expected_conditions 模块并使用别名 ECfrom selenium.webdriver.support import expected_conditions as EC
# 导入模块,加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By

# 显示等待,需要导入模块# 导入 WebDriverWait 类from selenium.webdriver.support.wait import WebDriverWait
# 导入 expected_conditions 模块并使用别名 ECfrom selenium.webdriver.support import expected_conditions as EC

# 加载驱动
driver = webdriver.Chrome()# 加载网站
driver.get('https://www.baidu.com')# 默认是0.5秒刷新一次# 等待时间总共是10秒,每隔1秒刷新一次# until 具体的条件内容
element = WebDriverWait(driver,10,1).until(# 判断元素是否加载出来
    EC.presence_of_element_located((By.ID,'kw')))
element.send_keys('hello')

隐式等待针对的是全局元素,全局生效,代码简单,只用于查找元素。

显示等待有很多的判断条件,适用范围更广,只针对某一个元素。

十四、案例

目标网站: https://juejin.cn/

需求:爬取文章内容,保存为 txt 格式,文件名以文章标题命名

分析:

翻页方式:滑动滚动条进行加载内容

1、设置先滚动5次,先把下面的内容加载出来,获取元素

2、先获取所有 li 元素,遍历 li 元素,进行点击操作

# 内置库import time
# 加载驱动from selenium import webdriver
# 定位元素from selenium.webdriver.common.by import By
# 正则import re

classJuJin(object):# 定义初始化方法def__init__(self):# 实例属性# 加载驱动
        self.driver = webdriver.Chrome()# 窗口最大化
        self.driver.maximize_window()# 加载网站
        self.driver.get('https://juejin.cn/')# 解析数据defparse_html(self):# 等待2秒
        time.sleep(2)# 获取 li 里的所有数据
        lis = self.driver.find_elements(By.XPATH,'//div[@class="entry-list list"]/li')# 循环处理数据for li in lis:# 捕获异常try:# 等待2秒
                time.sleep(2)# 获取文章标题标签
                a = li.find_element(By.CLASS_NAME,'title')# 点击标题标签进入详情页
                self.driver.execute_script('arguments[0].click();', a)# 切换窗口到内容页
                self.driver.switch_to.window(self.driver.window_handles[1])# 等待2秒
                time.sleep(2)# 获取标题标签
                title = self.driver.find_elements(By.CLASS_NAME,'article-title')# 获取文章内容标签
                contents = self.driver.find_elements(By.XPATH,'//div[@class="markdown-body cache"]/p')# 判断标题是否是空列表,如果是空列表,说明文章是广告文章ifnot title:# 获取标题标签
                    title = self.driver.find_elements(By.XPATH,'//a[@class="title"]/span')# 获取文章内容标签
                    contents = self.driver.find_elements(By.XPATH,'//div[@class="markdown-body"]/p')# 获取标题文本
                titles = title[0].text
                # 正则表达式替换标题特殊字符
                titles = re.sub(r'[,?/<>!: ()|"]','', titles)# 定义组装数据的变量
                s =''# 获取数据为列表,需循环取出for i in contents:# 组装数据
                    s += i.text +'\n'# 打印文章标题,内容# print(titles)# 保存数据
                self.save_data(titles, s)# 关闭当前窗口
                self.driver.close()# 切换窗口到列表页
                self.driver.switch_to.window(self.driver.window_handles[0])# 等待1秒
                time.sleep(1)except Exception as e:# 打印异常print(e)print("没有文章内容")# 关闭当前窗口
                self.driver.close()# 切换窗口到列表页
                self.driver.switch_to.window(self.driver.window_handles[0])# 保存数据defsave_data(self, title, contents):# 创建 txt 文本文档withopen(f'掘金/{title}.txt','w', encoding='utf-8')as f:# 文件写入
            f.write(contents)# 滚动方法defslide(self, height):# 滑动滚动条
        self.driver.execute_script(f'window.scrollTo(0,{height})')# 处理主逻辑defmain(self):# 获取窗口的高度
        heights = self.driver.get_window_size()['height']# 滑动次数
        page =1# 滑动while page <=5:
            self.slide(heights)# 加高度
            heights = heights + heights
            # 滑动次数+1
            page +=1# 等待1秒
            time.sleep(1)# 解析数据
        self.parse_html()# 创建对象
data = JuJin()# 调用 main 方法,开始执行主程序
data.main()

记录学习过程,欢迎讨论交流,尊重原创,转载请注明出处~

标签: 爬虫 python selenium

本文转载自: https://blog.csdn.net/muyuhen/article/details/132827735
版权归原作者 永远十八的小仙女~ 所有, 如有侵权,请联系我们删除。

“爬虫 — 自动化爬虫 Selenium”的评论:

还没有评论