python selenium_Python科普帖selenium

在本关,我将为你传授一个终极武器——selenium,通过它,可以解决攻破网站的反爬虫技术的问题。

0 selenium是什么?

selenium是什么呢?它是一个强大的Python库。它可以做什么呢?它可以用几行代码,控制浏览器,做出自动打开、输入、点击等操作,就像是有一个真正的用户在操作一样。

selenium能控制浏览器,这对解决我们刚刚提出的那几个问题,有什么帮助呢?

首先,当你遇到验证码很复杂的网站时,selenium允许让人去手动输入验证码,然后把剩下的操作交给机器。而对于那些交互复杂、加密复杂的网站,selenium问题简化,爬动态网页如爬静态网页一样简单。

什么是动态网页,什么又是静态网页呢?其实两种网页你都已经接触过了。

第1关教你用html写出的网页,就是静态网页。我们使用BeautifulSoup爬取这类型网页,因为网页源代码中就包含着网页的所有信息,因此,网页地址栏的URL就是网页源代码的URL。

b044dfd0ddf0763e143a9919fcd12ccc.png

后来,你开始接触更复杂的网页,比如QQ音乐,要爬取的数据不在HTML源代码中,而是在json中,你就不能直接使用网址栏的URL了,而需要找到json数据的真实URL。这就是一种动态网页。

48137b3d41dd64a9341f6d8ad169a407.png

不论数据存在哪里,浏览器总是在向服务器发起各式各样的请求,当这些请求完成后,它们会一起组成开发者工具的Elements中所展示的,渲染完成的网页源代码。在遇到页面交互复杂或是URL加密逻辑复杂的情况时,selenium就派上了用场,它可以真实地打开一个浏览器,等待所有数据都加载到Elements中之后,再把这个网页当做静态网页爬取就好了。

说了这么多优点,使用selenium时,当然也有美中不足之处。由于要真实地运行本地浏览器,打开浏览器以及等待网渲染完成需要一些时间,selenium的工作不可避免地牺牲了速度和更多资源,不过,至少不会比人慢。知道了它的优缺点,我们就开始学习如何使用selenium吧。

1 怎么用

首先,和其它所有Python库一样,selenium需要安装,方法也很简单, 使用pip安装。

1   pip install selenium # Windows电脑安装selenium
2 pip3 install selenium # Mac电脑安装selenium

selenium的脚本可以控制所有常见浏览器的操作,在使用之前,需要安装浏览器的驱动。我推荐的是Chrome浏览器,打开下面的链接,就可以下载Chrome的安装包了,Windows和Mac都有。

https://localprod.pandateacher.com/python-manuscript/crawler-html/chromedriver/ChromeDriver.html

在正式开始知识的讲解之前,我想首先让你体验一下selenium脚本程序在你的本地终端运行的效果。因为在学习selenium之初,如果能亲自看到浏览器自动弹出后的操作效果,对你后续的学习会有很大帮助。下面的代码就是本节课开头动图的代码。你现在不需要去理解具体的意思,等会儿就会学到每一行的用法。

现在只需要把这段代码复制到本地的代码编辑器中运行,体验一下你的浏览器为你自动工作的效果。当然,前提是你已经安装好了selenium库以及Chrome浏览器驱动。

# 本地Chrome浏览器设置方法
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/')
time.sleep(2)
teacher = driver.find_element_by_id('teacher')
teacher.send_keys('必须是吴枫呀')
assistant = driver.find_element_by_name('assistant')
assistant.send_keys('都喜欢')
time.sleep(1)
button = driver.find_element_by_class_name('sub')
time.sleep(1)
button.click()
time.sleep(1)

driver.close()

除了看程序运行,不如手动打开这个网站看看,做一遍和程序中一样的操作,URL给你:

https://localprod.pandateacher.com/python-manuscript/hello-spiderman/

首先引入眼帘的是【你好,蜘蛛侠!】几个大字,一秒之后,它会自动跳转到一个新的页面,请你输入最喜欢的老师和助教,你点击提交之后,它又会跳转到Python之禅的中英对照页面。

仔细看,你会发现,在这个过程中,网页URL一直没有变化,可见【你好,蜘蛛侠!】是个动态网页。体验了selenium之后,我们接下来正式开始代码的讲解。

1.1 设置浏览器引擎

和以前一样,使用一个新的Python库,首先要调用它。selenium有点不同,除了调用,还需要设置浏览器引擎。

# 本地Chrome浏览器设置方法

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

以上就是浏览器的设置方式:把Chrome浏览器设置为引擎,然后赋值给变量driver。driver是实例化的浏览器,在后面你会总是能看到它的影子,这也可以理解,因为我们要控制这个实例化的浏览器为我们做一些事情。

接下来,我们学习selenium的具体用法,这个部分的知识讲解,都会以你已经见到好几次的,【你好蜘蛛侠!】这个网站为例:

https://localprod.pandateacher.com/python-manuscript/hello-spiderman/

我们还是按照爬虫四步来讲解selenium的用法,看看selenium如何获取、解析与提取数据。由于本关中提取出的数据都不太复杂,直接在终端打印就好,不会涉及到储存数据这一步。

6107a10d5d5929c3fb45a4f9f0f6ceae.png

1.2 获取数据

首先看一下获取数据的代码怎么写吧。

import time

# 本地Chrome浏览器设置方法
from selenium import webdriver #从selenium库中调用webdriver模块
driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 打开网页
time.sleep(1)
driver.close() # 关闭浏览器

前面三行代码都是你学过的,调用模块,并且设置浏览器,只有后两行代码是新的。get(URL)是webdriver的一个方法,它的使命是为你打开指定URL的网页。刚才说过driver在这里是一个实例化的浏览器,因此,就是通过这个浏览器打开网页。

当一个网页被打开,网页中的数据就加载到了浏览器中,也就是说,数据被我们获取到了。driver.close()是关闭浏览器驱动,每次调用了webdriver之后,都要在用完它之后加上一行driver.close()用来关闭它。就像是,每次打开冰箱门,把东西放进去之后,都要记得关上门,使用selenium调用了浏览器之后也要记得关闭浏览器。

把上面的代码复制粘贴在你的本地电脑中运行,你可以看到,一个浏览器自动启动,并为你打开一个网页,停留一秒之后,浏览器关闭。

下一步,我们要让浏览器解析并提取数据,然后打印出来,让我们看到返回的运行结果。

1.3 解析与提取数据

我们在前面花两个关卡学习了使用BeautifulSoup解析网页源代码,然后提取其中的数据。selenium库同样也具备解析数据、提取数据的能力。它和BeautifulSoup的底层原理一致,但在一些细节和语法上有所出入。

首先明显的一个不同即是:selenium所解析提取的,是Elements中的所有数据,而BeautifulSoup所解析的则只是Network中第0个请求的响应。

本关开头我说过,用selenium把网页打开,所有信息就都加载到了Elements那里,之后,就可以把动态网页用静态网页的方法爬取了。

selenium是如何解析与提取数据的呢?我们现在来试试提取【你好蜘蛛侠!】网页中,元素的内容吧。

e8e02549b3b25ec938df6245f7d744f3.png

代码我写好了,点击运行看看吧:

# 本地Chrome浏览器设置方法
from selenium import webdriver #从selenium库中调用webdriver模块
driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面

time.sleep(2) # 等待2秒

label = driver.find_element_by_tag_name('label') # 解析网页并提取第一个标签

print(label.text) # 打印label的文本

driver.close() # 关闭浏览器

从运行结果中可以看到,我们提取出了(提示:吴枫)中的文本(提示:吴枫)。用time.sleep(2)等待两秒,是由于浏览器缓冲加载网页需要耗费一些时间,以及我在这个网页中设置了一秒之后才从首页跳转到输入页面,所以,等待两秒再去解析和提取比较稳妥。

这样来看,解析与提取数据,在这里其实只用了一行代码:

label = driver.find_element_by_tag_name('label') 

# 解析网页并提取第一个标签中的文字

你能否看出,是哪部分在做解析,哪部分在做提取?

先回想下,使用BeautifulSoup解析提取数据时,首先要把Response对象解析为BeautifulSoup对象,然后再从中提取数据。而在selenium中,获取到的网页存在了driver中,而后,解析与提取是同时做的,都是由driver这个实例化的浏览器完成。

所以,上个问题的答案是:解析数据是由driver自动完成的,提取数据是driver的一个方法。

清楚了解析与提取的本质,我们接下来详细讲解析数据的方法。

selenium当然不光能通过标签来提取数据,还有很多查找和提取元素的方法,都是非常直截了当的方法。

6301f44298810143f532d4721c5201af.png

你可以看出,提取数据的方法都是英文直译的意思。举例给你看看它们的用法,请仔细阅读下面代码的注释:

# 以下方法都可以从网页中提取出'你好,蜘蛛侠!'这段文字
find_element_by_tag_name:通过元素的名称选择
# 如

你好,蜘蛛侠!


# 可以使用find_element_by_tag_name('h1')
find_element_by_class_name:通过元素的class属性选择
# 如

你好,蜘蛛侠!


# 可以使用find_element_by_class_name('title')
find_element_by_id:通过元素的id选择
# 如

你好,蜘蛛侠!


# 可以使用find_element_by_id('title')
find_element_by_name:通过元素的name属性选择
# 如

你好,蜘蛛侠!


# 可以使用find_element_by_name('hello')

#以下两个方法可以提取出超链接

find_element_by_link_text:通过链接文本获取超链接
# 如你好,蜘蛛侠!
# 可以使用find_element_by_link_text('你好,蜘蛛侠!')
find_element_by_partial_link_text:通过链接的部分文本获取超链接
# 如你好,蜘蛛侠!
# 可以使用find_element_by_partial_link_text('你好')

以上就是提取单个元素的方法了。那么,我们提取出的元素是什么类呢?这种对象有什么属性和方法呢?我们现在就来看看。请阅读下面的代码,然后点击运行:

# 本地Chrome浏览器设置方法

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面

time.sleep(2) # 等待2秒

label = driver.find_element_by_tag_name('label') # 解析网页并提取第一个标签中的文字

print(type(label)) # 打印label的数据类型

print(label.text) # 打印label的文本

print(label) # 打印label

driver.close() # 关闭浏览器

运行结果有3行,分别是:

97e3b5bc4cfc5cd665517c65a3573a23.png

、label的文本(提示:吴枫)、以及label本身。

可见,提取出的数据属于WebElement类对象,如果直接打印它,返回的是一串对它的描述。而它与BeautifulSoup中的Tag对象类似,也有一个属性.text,可以把提取出的元素用字符串格式显示。

还想补充的是,WebElement类对象与Tag对象类似,它也有一个方法,可以通过属性名提取属性的值,这个方法是.get_attribute()。

ee3c274715a4eec71ec02b92a3376dd7.png

我们来举个例子:

c0cc82be4ee3bdb2932a7c61e5dc572a.png

我们试试,通过定位到上图中标亮的元素,然后提取出type这个属性的值text。

# 本地Chrome浏览器设置方法

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面

time.sleep(2) # 等待两秒

label = driver.find_element_by_class_name('teacher') # 根据类名找到元素

print(type(label)) # 打印label的数据类型

print(label.get_attribute('type')) # 获取type这个属性的值

driver.close() # 关闭浏览器

270e83872c91481b1d37b192b50bdca7.png

因此,我们可以总结出,selenium解析与提取数据的过程中,我们操作的对象转换:

f95795be7f3f3eeb3fdedcc60612cbb3.png

刚才,我们做的都是提取出网页中的第一个符合要求的数据,接下来,我们就看看提取多个元素的方法吧。

find_element_by_与BeautifulSoup中的find类似,可以提取出网页中第一个符合要求的元素;既然BeautifulSoup有提取所有元素的方法find_all,selenium也同样有方法。

方法也一样很简单,把刚才的element换成复数elements就好了。

b9cbbac00ca5bbef8efa7ecd60934ca5.png

我们来试试提取出【你好,蜘蛛侠!】的所有label标签中的文字。

# 本地Chrome浏览器设置方法

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面

time.sleep(2) # 等待两秒

labels = driver.find_elements_by_tag_name('label') # 根据标签名提取所有元素

print(type(labels)) # 打印labels的数据类型

print(labels) # 打印labels

driver.close() # 关闭浏览器

从运行结果可以看到,提取出的是一个列表,。而列表的内容就是WebElements对象,这些符号是对象的描述,我们刚才学过,需要用.text才能返回它的文本内容。

7beb3cd619b792702f8567b22cf34aaf.png

既然得到了列表,就可以和find_all返回的结果类似,同样用for循环遍历列表就可以提取出列表中的每一个值了。

labels = driver.find_elements_by_tag_name('label') # 根据标签名提取所有元素

for i in labels:

    print(i.text)

以上就是selenium的解析与提取数据的方法了。除了用selenium解析与提取数据,还有一种解决方案,那就是,使用selenium获取网页,然后交给BeautifulSoup解析和提取。

接下来,我们就看看,selenium与BeautifulSoup如何快乐地合作。

我们回顾一下BeautifulSoup的工作方式吧。

a143c3d0a5427de7c3d298904b04bcac.png

BeautifulSoup需要把字符串格式的网页源代码解析为BeautifulSoup对象,然后再从中提取数据。selenium刚好可以获取到渲染完整的网页源代码。

如何获取呢?也是使用driver的一个方法:page_source。

HTML源代码字符串 = driver.page_source

我们现在就来实操一下,获取【你好,蜘蛛侠!】的网页源代码:

# 本地Chrome浏览器设置方法

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面

time.sleep(2) # 等待两秒

pageSource = driver.page_source # 获取完整渲染的网页源代码
print(type(pageSource)) # 打印pageSource的类型
print(pageSource) # 打印pageSource
driver.close() # 关闭浏览器

我们成功获取并打印出了网页源代码O(∩_∩)O~~而且它的数据类型是。你还记不记得,用requests.get()获取到的是Response对象,在交给BeautifulSoup解析之前,需要用到.text的方法才能将Response对象的内容以字符串的形式返回。

而使用selenium获取到的网页源代码,本身已经是字符串了。

d44fa568b4a395344b9d26b4356e52a1.png

获取到了字符串格式的网页源代码之后,就可以用BeautifulSoup解析和提取数据了。到这里,解析与提取数据的方法就讲解完了。

关于selenium的用法,还有什么没有讲呢?对!就是我们在本关开头演示的功能,控制浏览器自动输入文本,并且点击提交。

我现在就为你解开这个谜底。

1.4 自动操作浏览器

其实,要做到自动操作的效果,你只需要新学两个方法就好了:

.send_keys() # 模拟按键输入,自动填写表单

.click() # 点击元素

用这两行代码,再搭配刚才所讲的解析提取数据的方法,就可以完成操作浏览器的效果了。学到这里,我们就可以写下全部代码了,这也正是我在开头给你的,让你复制到本地运行过的代码。

# 本地Chrome浏览器设置方法
from selenium import webdriver # 从selenium库中调用webdriver模块
import time # 调用time模块
driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器
driver.get('https://localprod.pandateacher.com/python-manuscript/hello-spiderman/') # 访问页面
time.sleep(2) # 暂停两秒,等待浏览器缓冲teacher = driver.find_element_by_id('teacher') # 找到【请输入你喜欢的老师】下面的输入框位置
teacher.send_keys('必须是吴枫呀') # 输入文字
assistant = driver.find_element_by_name('assistant') # 找到【请输入你喜欢的助教】下面的输入框位置
assistant.send_keys('都喜欢') # 输入文字
button = driver.find_element_by_class_name('sub') # 找到【提交】按钮
button.click() # 点击【提交】按钮
time.sleep(1)
driver.close() # 关闭浏览器

重点关注最后的8行代码,这段代码所做的是两次输入以及一次点击的操作,然后等待一秒,关闭浏览器驱动。由于这个代码的命令都是控制浏览器做一些操作,因此终端不会返回任何结果。

有没有发现,最后的6行代码是两两对应的,在每一次输入和点击之前,都要先定位到对应的位置,查找定位用的方法就是前面学过的,解析与提取数据的方法。比如,在输入你喜欢的老师之前,首先要在网页源代码中找到输入框的位置,方法还是我们之前学过的方法,点击开发者工具左上角的小箭头,然后把鼠标放在网页的空格处。

d4a25dd36567090e5f389b4e540378e1.png

从网页源代码可以看出,可以根据id="teacher",或者查找定位到这里。把提取到的位置信息赋值给teacher,然后再用teacher.send_keys()的方法输入你想填到这个空里的文本。这样就完成了一个完整的操作,后面的两个操作,方法都是类似的。由此,整个代码也就写出来了。

还想补充一个小知识,除了输入和点击的两个方法,经常配合它们会用到的,还有一个方法.clear(),用于清除元素的内容。

8014105a1d032559d82f6e2954daf37d.png

假如,在刚才的空格中,已经输入了【蜘蛛侠】,如果你想改成【吴枫】,就需要先用.clear()清除掉【蜘蛛侠】这几个文字,再填写新的文字。

到这里,本关知识讲解的部分就全部完成了。

2 本关总结

在这一关,我教你安装了selenium与Chrome驱动,本地的设置方法是这样的:

# 本地Chrome浏览器的可视模式设置:

from selenium import webdriver #从selenium库中调用webdriver模块

driver = webdriver.Chrome() # 设置引擎为Chrome,真实地打开一个Chrome浏览器

这种设置方法可以让你看到浏览器的操作过程。我想在这里补充的是,在本地的操作环境中,你还可以把自己电脑中的Chrome浏览器设置为静默模式,也就是说,让浏览器只是在后台运行,并不在电脑中打开它的可视界面。

因为在做爬虫时,通常不需要打开浏览器,爬虫的目的是爬到数据,而不是观看浏览器的操作过程,在这种情况下,就可以使用浏览器的静默模式,它的设置方法是这样的:

# 本地Chrome浏览器的静默默模式设置:
from selenium import webdriver #从selenium库中调用webdriver模块
from selenium.webdriver.chrome.options import Options # 从options模块中调用Options类
chrome_options = Options() # 实例化Option对象
chrome_options.add_argument('--headless') # 把Chrome浏览器设置为静默模式
driver = webdriver.Chrome(options = chrome_options) # 设置引擎为Chrome,在后台默默运行

它与教学系统中所采用的浏览器设置方法有些类似,如果你想在本地运行静默模式,就可以这样设置。与上面浏览器的可视设置相比,3、5、6行代码是新增的,首先调用了一个新的类——Options,然后通过它的方法和属性,给浏览器输入了一个参数——headless。第7行代码中,把刚才所做的浏览器设置传给了Chrome浏览器。

浏览器的可视模式与静默模式的设置,就是以上四行代码的区别。你懂的,这之后所有代码都是一样的。

嘱咐好了所有要讲给你的知识,那就继续每一关结尾例行的总结吧~

我们刚才学习了使用selenium获取数据的方法:.get('URL')。

解析与提取数据的方法:

735dc510fefec158115903a34d0f7e19.png

以及在这个过程中,对象的转换过程:

59274fdeebe34e4f08ad514a37a5a664.png

除了上面的方法,selenium还可以搭配BeautifulSoup解析提取数据,前提是先获取字符串格式的网页源代码。

HTML源代码字符串 = driver.page_source

以及自动操作浏览器的一些方法。

eb09a2661fd9f8814c9b7885571f0503.png

还有,在用完浏览器之后,要记得关闭它,以免资源浪费,在代码的结尾处加一行driver.close()就好。

到这里,你应该能感受到,Selenium是一个强大的网络数据采集工具,它的优势是简单直观,而它当然也有缺点。由于是真实地模拟人操作浏览器,需要等待网页缓冲的时间,在爬取大量数据的时候,速度会比较慢。

通常情况,在爬虫项目中,selenium都是用在其它方法无法解决,或是很难解决的问题时,才会用到。当然,除了爬虫,selenium的使用场景还有很多。比如:它可以控制网页中图片文件的显示、控制CSS和JavaScript的加载与执行等等。我们的课程只是带你入门,讲了一些简单常用的操作,还想进一步学习的话,可以通过selenium的官方文档链,目前只有英文版:

https://seleniumhq.github.io/selenium/docs/api/py/api.html

还可以参考这个中文文档:

https://selenium-python-zh.readthedocs.io/en/latest/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值