爬虫-浏览器自动化

什么是selenium

selenium是浏览器自动化测试框架,原本用于网页测试。但到了爬虫领域,它又成为了爬虫的好帮手。有了 selenium ,我们便不再需要判断网页数据加载的方式,只要让 selenium 自动控制浏览器,就像有双无形的手,控制着你的鼠标和键盘,自动地帮你干活。爬取数据?自动抢票?这些当然统统都不在话下。

安装selenium

和安装python的第三方库是一样的

pip install selenium

selenium还需要安装相应的浏览器驱动才能控制浏览器。强烈推荐使用Chorme浏览器。

查看自己电脑上的浏览器版本,依次点击浏览器右上角的 三个点 - 帮助 - 关于 Google Chrome。

将下载的对应版本的的 chromedriver 解压缩,Windows 系统得到 chromedriver.exe,这个就是我们需要的浏览器驱动。我们要将它放到 Python 所在安装目录里。

为了验证驱动是否安装成功,Windows 系统在的 命令行 或者 Anaconda Prompt 中输入 chromedriver 命令,如果出现类似下图所示的内容,就证明驱动已经安装成功了。

打开浏览器

来看下如何用selenium打开Chrom浏览器

python 复制代码
# 从 selenium 中导入 webdriver(驱动)
from selenium import webdriver

# 选择 Chrome 浏览器并打开
browser = webdriver.Chrome()

获取数据

python 复制代码
# 从 selenium 中导入 webdriver(驱动)
from selenium import webdriver

# 选择 Chrome 浏览器打开
browser = webdriver.Chrome()
# 打开网页
browser.get('https://wpblog.x0y1.com')
# 关闭浏览器
browser.quit()

browser 是我们实例化的浏览器。我们将网址传给 browser 对象的 get() 方法,即可打开对应的网页。最后调用 quit() 方法将浏览器关闭。

我们的目的是获取数据,接下来让我们用 browser 对象的 page_source 属性来获取网页的源代码。值得注意的是,用 selenium 获取的网页源代码是数据加载完毕后最终的源代码,也就是网页加载后通过 API 获取的数据也在这个源代码中。

因此,我们就不用再区分要爬取的网页是静态网页还是动态网页了,在 selenium 眼里统统都一样。

|------------------------------|-------------|
| 代码 | 作用 |
| browser = webdriver.Chrome() | 打开Chrome浏览器 |
| browser.get("网址") | 打开网页 |
| browser.page_source | 获取网页源代码 |
| browser.quit() | 关闭浏览器 |

处理数据

我们来看看如何用 selenium 处理数据。我们以获取博客的 h1 元素为例。

python 复制代码
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://wpblog.x0y1.com')
h1 = browser.find_element(by='tag name', value='h1')
# 上面的代码也可以写成  
# h1 = browser.find_element('tag name', 'h1')
print(h1.text)
browser.quit()

|---------------------------------------------------|------------------|
| 方法 | 作用 |
| find_element(by = 'tag name', value=...) | 通过标签查找元素 |
| find element(by = 'class name', value=...) | 通过 class 属性名查找元素 |
| find element(by = 'id', value=...) | 通过 id 查找元素 |
| find element(by = 'name', value=...) | 通过 name 属性查找元素 |
| find element(by = 'Link text', value=...) | 通过链接文本查找元素 |
| find element(by = 'partial link text', value=...) | 通过链接的部分文本查找元素 |

这些方法找到的元素(返回值)都是 WebElement 对象,它和 BeautifulSoup 里的 Tag 对象一样,也有一个 text 属性,一样也是获取元素里的文本内容。

BeautifulSoup 中通过 select() 方法查找所有被所传入的 CSS 选择器选中的元素。刚才介绍的那些方法都是查找第一个符合条件的元素,接下来我们来看看 selenium 中查找所有符合条件的元素的方法。

这些方法非常简单,直接把 find_element() 方法改成 find_elements() 方法即可:

|----------------------------------------------------|------------------|
| 方法 | 作用 |
| find_elements(by = 'tag name', value=...) | 通过标签查找元素 |
| find elements(by = 'class name', value=...) | 通过 class 属性名查找元素 |
| find elements(by = 'id', value=...) | 通过 id 查找元素 |
| find elements(by = 'name', value=...) | 通过 name 属性查找元素 |
| find elements(by = 'Link text', value=...) | 通过链接文本查找元素 |
| find elements(by = 'partial link text', value=...) | 通过链接的部分文本查找元素 |

比如获取网页源代码中所有的a元素

python 复制代码
from selenium import webdriver

browser = webdriver.Chrome()
browser.get('https://wpblog.x0y1.com')
# 注意下面是 elements
a_tags = browser.find_elements('tag name', 'a')

for tag in a_tags:
  print(tag.text)
browser.quit()

值得一提的是,WebElement 对象也可以调用 selenium 查找元素的方法。这样就和 BeautifulSoup 中的 Tag 对象一样,可以一层一层的查找元素,直到找到为止。

BeautifulSoup 的原理是将网页源代码的字符串形式解析成 BeautifulSoup 对象 ,然后通过 BeautifulSoup 对象 的属性和方法提取出我们需要的数据。发现没有?BeautifulSoup 只需要一个网页源代码的字符串形式即可。

之前我们都是使用 requests 库获取网页源代码,并通过 text 属性取得其字符串形式。而 selenium 获取网页后的 page_source 属性值正是字符串格式的!

以上面获取博客网页源代码中所有的 a 元素 为例,加上 BeautifulSoup 可以这样写:

python 复制代码
from selenium import webdriver
from bs4 import BeautifulSoup

browser = webdriver.Chrome()
browser.get('https://wpblog.x0y1.com')
# 用 BeautifulSoup 解析网页源代码
soup = BeautifulSoup(browser.page_source, 'html.parser')
a_tags = soup.select('a')
for tag in a_tags:
  print(tag.text)
browser.quit()

我写了一个两者结合爬取豆瓣读书的代码

python 复制代码
import time
from selenium import webdriver
from bs4 import BeautifulSoup


browser = webdriver.Chrome()
browser.get("https://book.douban.com/top250/")
time.sleep(2)

#soup = BeautifulSoup(res.text, 'html.parser')
soup = BeautifulSoup(browser.page_source, 'html.parser')
#print(soup)
# 所有书名所在元素
book_name_tags = soup.select("a")
#print(book_name_tags)
book_names = []
for book_name in book_name_tags:
    name = book_name.attrs
    if 'title' in name:
        book_names.append(name['title'])

# 所有书籍信息所在元素
book_info_tags = soup.find_all('p', class_="pl")

for i in range(len(book_names)):
    name = book_names[i]
    author = book_info_tags[i].text.split('/')[0]
    publisher = book_info_tags[i].text.split('/')[-3]
    print("%s / %s / %s" % (name, author, publisher))

browser.quit()

返回的结果如下:

红楼梦 / [清] 曹雪芹 著 / 人民文学出版社

活着 / 余华 / 作家出版社

1984 / [英] 乔治·奥威尔 / 北京十月文艺出版社

哈利·波特 / J.K.罗琳 (J.K.Rowling) / 人民文学出版社

三体全集 / 刘慈欣 / 重庆出版社

百年孤独 / [哥伦比亚] 加西亚·马尔克斯 / 南海出版公司

飘 / [美国] 玛格丽特·米切尔 / 译林出版社

动物农场 / [英] 乔治·奥威尔 / 上海译文出版社

三国演义(全二册) / [明] 罗贯中 / 人民文学出版社

房思琪的初恋乐园 / 林奕含 / 北京联合出版公司

福尔摩斯探案全集(上中下) / [英] 阿·柯南道尔 / 1981-8

白夜行 / [日] 东野圭吾 / 南海出版公司

小王子 / [法] 圣埃克苏佩里 / 人民文学出版社

安徒生童话故事集 / (丹麦)安徒生 / 人民文学出版社

天龙八部 / 金庸 / 生活·读书·新知三联书店

撒哈拉的故事 / 三毛 / 哈尔滨出版社

呐喊 / 鲁迅 / 人民文学出版社

邓小平时代 / 【美】傅高义 (Ezra.F.Vogel) / 生活·读书·新知三联书店

悉达多 / [德] 赫尔曼·黑塞 / 天津人民出版社

杀死一只知更鸟 / [美] 哈珀·李 / 译林出版社

明朝那些事儿(1-9) / 当年明月 / 中国海关出版社

失踪的孩子 / [意] 埃莱娜·费兰特 / 人民文学出版社

新名字的故事 / [意] 埃莱娜·费兰特 / 人民文学出版社

野草 / 鲁迅 / 人民文学出版社

沉默的大多数 / 王小波 / 中国青年出版社

控制浏览器

我们要想登录博客,那必须具备登录的动作,再学习两个方法,分别是:click() 和 send_keys()

|-------------|--------|
| 方法 | 作用 |
| click() | 点击元素 |
| send_keys() | 模拟按键输入 |

看下其在代码中的应用

python 复制代码
from selenium import webdriver
import time

browser = webdriver.Chrome()
# 打开博客
browser.get('https://wpblog.x0y1.com')
# 找到登录按钮
login_btn = browser.find_element('link text', '登录')
# 点击登录按钮
login_btn.click()
# 等待 2 秒钟,等页面加载完毕
time.sleep(2)
# 找到用户名输入框
user_login = browser.find_element('id', 'user_login')
# 输入用户名
user_login.send_keys('codetime')
# 找到密码输入框
user_pass = browser.find_element('id', 'user_pass')
# 输入密码
user_pass.send_keys('shanbay520')
# 找到登录按钮
wp_submit = browser.find_element('id', 'wp-submit')
# 点击登录按钮
wp_submit.click()
# 找到 Python 分类文章链接
python_cat = browser.find_element('css selector', 'section#categories-2 ul li a')
# 点击该分类
python_cat.click()
# 找到跳转的页面中的所有文章标题元素
titles = browser.find_elements('css selector', 'h2.entry-title a')

# 找到标题元素中内含的链接
links = [i.get_attribute('href') for i in titles]
# 依次打开 links 中的文章链接
for link in links:
  browser.get(link)
  # 获取文章正文内容
  content = browser.find_element('class name', 'entry-content')
  print(content.text)
  
browser.quit()
相关推荐
七夜zippoe11 小时前
CANN Runtime任务描述序列化与持久化源码深度解码
大数据·运维·服务器·cann
Fcy64812 小时前
Linux下 进程(一)(冯诺依曼体系、操作系统、进程基本概念与基本操作)
linux·运维·服务器·进程
袁袁袁袁满12 小时前
Linux怎么查看最新下载的文件
linux·运维·服务器
代码游侠12 小时前
学习笔记——设备树基础
linux·运维·开发语言·单片机·算法
Harvey90313 小时前
通过 Helm 部署 Nginx 应用的完整标准化步骤
linux·运维·nginx·k8s
珠海西格电力科技14 小时前
微电网能量平衡理论的实现条件在不同场景下有哪些差异?
运维·服务器·网络·人工智能·云计算·智慧城市
释怀不想释怀14 小时前
Linux环境变量
linux·运维·服务器
zzzsde14 小时前
【Linux】进程(4):进程优先级&&调度队列
linux·运维·服务器
深蓝电商API15 小时前
处理字体反爬:woff字体文件解析实战
爬虫·python
聆风吟º16 小时前
CANN开源项目实战指南:使用oam-tools构建自动化故障诊断与运维可观测性体系
运维·开源·自动化·cann