本课程共五个章节,课程地址:
【Python爬虫教程】花9888买的Python爬虫全套教程2021完整版现分享给大家!(已更新项目)——附赠课程与资料_哔哩哔哩_bilibili
第五章
- selenium概述
- selenium各种神奇操作
- 多窗口调度及iframe处理
- 无头浏览器
- 超级鹰基本使用
- 超级鹰干超级鹰
- 模拟12306登录
目录
第三步:在搜索框里输入“python”,按下回车或点击“搜索”按钮
如何拿到页面代码 Elements(经过数据加载及js执行后的结果的html内容,不是页面源代码)
(一)selenium概述
想抓取电影票房:艺恩娱数
右键 ——> 查看网页源代码,发现数据不在页面源代码中
故而 f12 ——> Network
内容正常(网页貌似又改版了emmm,那就用课程PPT上的截图)
我们在抓取一些普通网页的时候 requests 基本上是可以满足的,但是如果遇到一些特殊的网站,它的数据是经过加密的,而浏览器却能够正常显示出来,那我们通过 requests 抓取到的内容可能就不是我们想要的结果了。例如:
电影票房数据,在浏览器上看的时候是正常的,那么按照之前的逻辑,我们只需要看看数据是通过哪个请求拿到的就可以进行模拟请求了
数据找到了,点击 Preview 预览:
我们发现这个数据是经过加密算法的,直接通过 requests 拿到这些内容必须要解密才能看到真实数据,但是该网站采用的加密方式又不是那么容易破解。此时,如果我能通过我的程序直接调用浏览器,让浏览器去解密这些内容,我们直接拿结果就好了。这就引出了本章的 selenium
- 需求:能不能让我的程序连接到浏览器,让浏览器来完成各种复杂的操作,我们只接收最终的结果
- selenium:本身是一个自动化测试工具,可以启动一个全新的浏览器,并从浏览器中提取到你想要的内容
- 程序员可以从 selenium 中直接提取网页上的各种信息。随着各种网站的反爬机制的出现,selenium 越来越受到程序员的喜爱
- 适用场景:爬取加密之后的东西;爬取动态加载数据的网页
- 缺点:要启动一个第三方的软件(浏览器),并且还要等待浏览器把数据渲染完毕,这个过程必然是很耗时的,所以它慢
环境搭建
安装:
pip install selenium --trusted-host pypi.tuna.tsinghua.edu.cn
selenium 与其他库不同的地方在于:它要启动你电脑上的浏览器,这就需要一个驱动程序来辅助
下载浏览器驱动:
chrome浏览器驱动地址:
查询自己chrome浏览器的版本:
如果版本号对不上,可以对应前三位即可,即104.0.5112,最后一位找最接近的:
win64 选 win32 即可
下载并解压,把解压缩的浏览器驱动 chromedriver 放在 python解释器 所在的文件夹
python解释器所在的文件夹怎么找? 随便运行一个 .py 文件
使用
测试一下,让 selenium 启动谷歌浏览器:
from selenium.webdriver import Chrome # 导入谷歌浏览器的类
# 1.创建浏览器对象
web = Chrome()
# 2.打开一个网址
web.get("http://www.baidu.com")
print(web.title)
运行一下会发现浏览器自动打开了,并且输入了网址,也能拿到网页上的 title标题(百度一下,你就知道)
(二)selenium各种神奇操作
selenium 不但可以打开浏览器,还可以对浏览器各种操作,如点击、查找都可以
我们直接上案例:抓取拉勾网招聘python工程师的招聘信息
第一步:打开拉勾网
from selenium.webdriver import Chrome
web = Chrome()
web.get("http://lagou.com")
第二步:点击 “北京” 按钮
想要点击这个按钮,我们需要先定位到这个按钮,然后再点击 selenium 想要定位的某个元素
from selenium.webdriver.common import by
# 找到某个元素,点击它
# web.find_elements() 找全部;web.find_element() 找一个
el = web.find_element(by.By.XPATH, '//*[@id="changeCityBox"]/ul/li[1]/a') # 北京的按钮
el.click() # 点击事件
第三步:在搜索框里输入“python”,按下回车或点击“搜索”按钮
from selenium.webdriver.common import by
from selenium.webdriver.common.keys import Keys # 模拟键盘上的键
import time
time.sleep(1) # 让浏览器缓一会,等页面加载完(ajax)
# 找到输入框,输入python ——> 输入回车(以这种为例)/点击搜索按钮(和上面的思路一样,不再赘述)
web.find_element(by.By.XPATH, '//*[@id="search_input"]').send_keys("python", Keys.ENTER) # 回车
send_keys() :
如果我们给出的是一个字符串,就是输入文本;
如果给出的是一个键盘指令,那就按下键盘,比如,我想要按回车按钮,就是这样的:
from selenium.webdriver.common.keys import Keysweb.find_element(by.By.XPATH, ' ' ).send_keys( Keys.ENTER)Keys里几乎包含了我们需要的所有特殊按键
第四步:查找存放数据的位置,进行数据提取
复制岗位名称的XPath
复制薪资的XPath
其他以此类推
time.sleep(1)
# 查找存放数据的位置,进行数据提取
li_list = web.find_elements(by.By.XPATH, '//*[@id="jobList"]/div[1]/div') # 找到页面中存放数据的所有url
for li in li_list:
job_name = li.find_element(by.By.XPATH, './div[1]/div[1]/div[1]/a').text # 职位名称
job_price = li.find_element(by.By.XPATH, './div[1]/div[1]/div[2]/span').text # 薪资
company_name = li.find_element(by.By.XPATH, './div[1]/div[2]/div[1]/a').text # 公司名称
print(company_name, job_name, job_price)
完整代码:
from selenium.webdriver import Chrome
from selenium.webdriver.common import by
from selenium.webdriver.common.keys import Keys # 模拟键盘上的键
import time
web = Chrome()
web.get("http://lagou.com")
# 找到某个元素,点击它
# web.find_elements() 找全部;web.find_element() 找一个
el = web.find_element(by.By.XPATH, '//*[@id="changeCityBox"]/ul/li[1]/a') # 北京的按钮
el.click() # 点击事件
time.sleep(1) # 让浏览器缓一会,等页面加载完(ajax)
# 找到输入框,输入python ——> 输入回车(以这种为例)/点击搜索按钮(和上面的思路一样,不再赘述)
web.find_element(by.By.XPATH, '//*[@id="search_input"]').send_keys("python", Keys.ENTER) # 回车
time.sleep(1)
# 查找存放数据的位置,进行数据提取
li_list = web.find_elements(by.By.XPATH, '//*[@id="jobList"]/div[1]/div') # 找到页面中存放数据的所有url
for li in li_list:
job_name = li.find_element(by.By.XPATH, './div[1]/div[1]/div[1]/a').text # 职位名称
job_price = li.find_element(by.By.XPATH, './div[1]/div[1]/div[2]/span').text # 薪资
company_name = li.find_element(by.By.XPATH, './div[1]/div[2]/div[1]/a').text # 公司名称
print(company_name, job_name, job_price)
(三)多窗口调度及iframe处理
窗口之间的切换:
上节我们已经可以通过 selenium 拿到拉勾网的招聘信息了,但是信息不够全面,我们希望得到的不仅仅是一个岗位名称和公司名称,而是更加详细的职位描述和岗位要求
此时问题就来了,我们可以在搜索页面点击进入到这个详情页,然后就可以看到想要的职位描述了。但是,这时就涉及到如何从一个窗口转向另一个窗口(切换选项卡)
想要爬取上图中的 “职位描述”
- 首先,先通过 selenium 定位到搜索页上的职位超链接
- 我们看到的是新窗口的内容,但是在 selenium 的视角里,窗口依然停留在刚才那个窗口,此时必须要将窗口调整到最新的窗口上才可以
from selenium.webdriver import Chrome
from selenium.webdriver.common import by
from selenium.webdriver.common.keys import Keys
import time
web = Chrome()
web.get("http://lagou.com")
web.find_element(by.By.XPATH , '//*[@id="cboxClose"]').click() # 点x
time.sleep(1)
web.find_element(by.By.XPATH, '//*[@id="search_input"]').send_keys("python", Keys.ENTER)
time.sleep(1)
web.find_element(by.By.XPATH, '//*[@id="jobList"]/div[1]/div[1]/div[1]/div[1]/div[1]/a').click()
# 如何进入到新窗口中进行提取
# 注意,在selenium的眼中,新窗口默认是不切换过来的
web.switch_to.window(web.window_handles[-1]) # 切换到选项栏里的最后一个窗口
# 在新窗口中提取内容
job_detail = web.find_element(by.By.XPATH, '//*[@id="job_detail"]/dd[2]/div').text # 职位描述
print(job_detail)
爬取完毕后,再回到原来的页面:
# 关掉子窗口
web.close()
# 变更selenium的视角,将视角切换到原来的窗口
web.switch_to.window(web.window_handles[0])
print(web.find_element(by.By.XPATH, '//*[@id="jobList"]/div[1]/div[1]/div[1]/div[1]/div[1]/a').text)
页面中遇到了 iframe 如何处理
之前我们抓取过一个网站,里面把视频内容嵌套在一个 iframe 中。那么换成了 selenium 该如何应对呢?
梦华录详情介绍-梦华录在线观看-梦华录迅雷下载 - 看剧柒柒-77影视-77电影-看剧77-77影视-影视大全免费追剧-柒柒看剧
# 如果页面中遇到了 iframe 如何处理
web.get("https://kanju77.com/vy/107438-1-1/")
# 处理iframe的话,必须先拿到iframe,然后切换视角到iframe,才可以拿数据
iframe = web.find_element(by.By.XPATH, '//*[@id="playleft"]/iframe')
web.switch_to.frame(iframe) # 切换到iframe
tx = web.find_element(by.By.XPATH, '//*[@id="mse"]/video').get_attribute("src")
print(tx)
# 再从iframe里切换回原页面
# web.switch_to.default_content()
播放器中的视频地址是一个 blob:https,它并不是一种协议,而是 html5 中 blob对象在赋给video标签后生成的一串标记,简单来说,就是防止爬虫能直接拿到视频下载地址,中间倒了一手
(四)无头浏览器
前三节我们已经了解了 selenium 的基本使用,但是每次打开浏览器的时间都比较长,这就很耗时。我们写的是爬虫程序,目的是数据,并不是想看网页,那能不能让浏览器在后台跑呢?这就涉及到无头浏览器的内容
课程上案例的网址已经失效了,但还是以其代码为例来抓取电影票房,说明 selenium 对下拉列表的处理
下拉列表:select 标签
另一种:通过css动态渲染出下拉效果
例如:
<select>
<option value=1>哈哈</option>
</select>
value就是1,visible_text就是哈哈
正常的有浏览器窗口的方式来抓取:
from selenium.webdriver import Chrome
from selenium.webdriver.common import by
from selenium.webdriver.support.select import Select
import time
web = Chrome()
web.get("https://www.endata.com.cn/BoxOffice/BO/Year/index.html")
# 定位到下拉列表(电影票房选取年份 select)
sel_el = web.find_element(by.By.XPATH, '//*[@id="OptionDate"]') # 元素类型
# 对元素进行包装, 包装成下拉菜单
sel = Select(sel_el) # select类型
# 让浏览器进行调整选项(切换年份 option)
for i in range(len(sel.options)): # i就是每一个下拉框选项的索引位置
# .select_by_index 根据索引进行选择
# .select_by_value 根据value进行选择
# .select_by_visible_text 根据你所见的文本进行选择
sel.select_by_index(i) # 按照索引进行切换
time.sleep(2) # 每次切换都发送一次网络请求,所以要等它加载完
table = web.find_element(by.By.XPATH, '//*[@id="TableList"]/table')
print(table.text) # 打印所有文本信息
print("===================================")
print("运行完毕. ")
web.close()
让 selenium 在后台执行:
主要添加的部分:
from selenium.webdriver.chrome.options import Options # 配置
# 准备好参数配置
opt = Options()
opt.add_argument("--headless")
opt.add_argument("--disable-gpu")
web = Chrome(options=opt) # 把参数配置设置到浏览器中
完整代码:
from selenium.webdriver import Chrome
from selenium.webdriver.chrome.options import Options # 配置
from selenium.webdriver.common import by
from selenium.webdriver.support.select import Select
import time
# 准备好参数配置
opt = Options()
opt.add_argument("--headless")
opt.add_argument("--disable-gpu")
web = Chrome(options=opt) # 把参数配置设置到浏览器中
web.get("https://www.endata.com.cn/BoxOffice/BO/Year/index.html")
# 定位到下拉列表(电影票房选取年份 select)
sel_el = web.find_element(by.By.XPATH, '//*[@id="OptionDate"]') # 元素类型
# 对元素进行包装, 包装成下拉菜单
sel = Select(sel_el) # select类型
# 让浏览器进行调整选项(切换年份 option)
for i in range(len(sel.options)): # i就是每一个下拉框选项的索引位置
# .select_by_index 根据索引进行选择
# .select_by_value 根据value进行选择
# .select_by_visible_text 根据你所见的文本进行选择
sel.select_by_index(i) # 按照索引进行切换
time.sleep(2) # 每次切换都发送一次网络请求,所以要等它加载完
table = web.find_element(by.By.XPATH, '//*[@id="TableList"]/table')
print(table.text) # 打印所有文本信息
print("===================================")
print("运行完毕. ")
web.close()
如何拿到页面代码 Elements(经过数据加载及js执行后的结果的html内容,不是页面源代码)
标准的 ajax 请求把数据加载到页面当中,不是在页面源代码里体现。所以右键 ——> 查看网页源代码 和 f12 ——> Elements(看到的是js ajax加载完了,实时的用户所见即所得的内容) 看到的内容可能不一样
# 准备好参数配置
opt = Options()
opt.add_argument("--headless")
opt.add_argument("--disable-gpu")
web = Chrome(options=opt) # 把参数配置设置到浏览器中
web.get("https://www.endata.com.cn/BoxOffice/BO/Year/index.html")
time.sleep(2) # 等待js加载完数据
# 如何拿到页面代码Elements(经过数据加载以及js执行之后的结果的html内容)
print(web.page_source)