Selenium是一个Web的自动测试工具, 最初是为了网站自动化测试二开发的, Selenium可以直接运行在浏览器上,特支持所有主流的浏览器(包括PhantomJS这些无界面的浏览器), 可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏.
PhantomJS是一个基于Webkit的"无界面"(headless)浏览器, 它会把网站加载到内存并执行页面上的JavaScript.
下载地址: http://phantomjs.org/download.html
Chromedriver也是一个能够被selenium驱动的浏览器,但是和PhantomJS的区别在于它是有界面的.
下载地址:https://npm.taobao.org/mirrors/chromedriver
最简单的安装方式: 解压后吧bin目录下的可执行文件移动到环境变量下
wget https://bitbucket.org/ariya/phantomjs/downloads/phantomjs-2.1.1-linux-x86_64.tar.bz2
tar -xvjf phantomjs-2.1.1-linux-x86_64.tar.bz2
sudo cp -R phantomjs-2.1.1-linux-x86_64 /usr/local/share/
sudo ln -sf /usr/local/share/phantomjs-2.1.1-linux-x86_64/bin/phantomjs /usr/local/bin/
chromedriver下载地址:
http://chromedriver.storage.googleapis.com/index.html
----- Linux 下安装方式
chromedriver_linux64.zip : 版本 ChromeDriver v2.22 (2016-06-06)
(支持 Chrome v49-52,当前Ubuntu虚拟机下的Chrome版本为50.0)
1. unzip chromedriver_linux64.zip
2. sudo chmod +x chromedriver
3. sudo mv chromedriver /usr/local/bin/
----- MacOS X 下安装方式
chromedriver_mac64.zip : 版本 ChromeDriver v2.32 (2017-08-30)
(支持 Chrome v59-61)
1. 安装 同Linux
----- Windows 下安装方式
chromedriver_win32.zip : 版本 ChromeDriver v2.32 (2017-08-30)
(支持 Chrome v59-61)
1. 解压 chromedriver_win32.zip
2. 将 chromedriver 移动到 Python安装目录下
(其实放哪都可以,但是需要配环境变量,放Python安装目录下省事)
注意:Chromedriver和电脑上的chrome版本有对应关系,建议使用最新的Chromedriver版本并且更新chrome浏览器到最新版
pip install selenium
selenium通过控制浏览器,对应获取的数据都是elements的内容.
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
# driver = webdriver.PhantomJS(executable_path='/home/worker/Desktop/driver/phantomjs')
driver = webdriver.Chrome(executable_path=r''/home/worker/Desktop/driver/chromedriver')
# 想一个url发起请求
driver.get("https://www.baidu.com/")
# 保存页面
driver.save_screenshot("baidu.png")
time.sleep(5)
# 退出
driver.quit()
以百度搜索为例:
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
# driver = webdriver.PhantomJS(executable_path='/home/worker/Desktop/driver/phantomjs')
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
# 想一个url发起请求
driver.get("https://www.baidu.com/")
driver.find_element_by_id('kw').send_keys('python')
time.sleep(5)
driver.find_element_by_id('su').click()
time.sleep(5)
# 退出
driver.quit()
driver.page_source # 查看网页源码
driver.get_cookies() # # 获取当前浏览器的全部cookies
driver.current_url # 获取当前页面的url
driver.close() #退出当前页面
driver.quit() #退出浏览器
模拟百度搜索’传智博客’
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
driver.get("https://www.baidu.com/")
driver.find_element_by_id('kw').send_keys("传智播客")
time.sleep(5)
driver.find_element_by_id('su').click()
time.sleep(5)
# 退出
driver.quit()
定位元素语法:
find_element_by_id(返回一个元素)
find_elements_by_xpatn(返回一个包含元素的列表)
find_elements_by_link_text(根据连接文本获取元素列表)
find_elements_by_partial_link_text(根据连接包含的文本获取袁旭列表)
find_elements_by_tag_name(根据标签名获取元素列表)
find_elements_by_class_name(根据类名获取元素列表)
注意:
find_element和find_elements的区别: 多了s就返回列表, 没有s就返回匹配到的第一个元素
by_link_text和by_partial_link_text的区别: 全部文本和包含某个文本
以豆瓣首页为例: https://www.douban.com/
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
driver.get("https://www.douban.com/")
# find_element_by_id (返回一个元素)
ret1 = driver.find_element_by_id("anony-nav")
print("ret1: {}".format(ret1))
# find_elements_by_xpath (返回一个包含元素的列表)
ret2 = driver.find_elements_by_xpath('//*[@id="anony-nav"]/h1')
for el in ret2:
print("ret2: {}".format(el))
# find_elements_by_link_text (根据连接文本获取元素列表)
ret3 = driver.find_elements_by_link_text("下载豆瓣 App")
for el in ret3:
print("ret3: {}".format(el))
# find_elements_by_partial_link_text (根据链接包含的文本获取元素列表)
ret4 = driver.find_elements_by_partial_link_text("豆瓣")
for el in ret4:
print("ret4: {}".format(el))
# find_elements_by_tag_name (根据标签名获取元素列表)
ret5 = driver.find_elements_by_tag_name("h1")
for el in ret5:
print("ret5: {}".format(el))
# find_elements_by_class_name (根据类名获取元素列表)
ret6 = driver.find_elements_by_class_name("section")
for el in ret6:
print("ret6: {}".format(el))
time.sleep(5)
# 退出
driver.quit()
find_element仅仅能获取元素, 不能够直接获取其中的数据,如果需要获取其中的数据, 需要使用一下方法:
driver.get_cookies(): 获取的是完整的cookie信息, 不光有name、value, 还有domain等其他信息.
# 把cookie转化成字典
dookie_dict = {cookie['name']: cookie['value'] for cookie in driver.get_cookies()}
# 删除一条cookie
driver.delete_cookie('cookie_name')
# 删除所有的cookie
driver.delete_cookies()
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
driver.get("http://www.itcast.cn/")
time.sleep(2)
js = 'window.scrollTo(0,document.body.scrollHeight)' # js语句:页面到最后
driver.execute_script(js) # 执行js的方法
time.sleep(5)
# 退出
driver.quit()
一个 浏览器肯定会有很多窗口, 所有我们肯定要有方法来实现窗口的切换. 切换窗口的方法如下:
# 1. 获取当前所有的窗口
current_windows = driver.window_handles
# 2.根据窗口索引进行切换
driver.switch_to.window(current_windows[1])
完整代码:
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
# 打开第一个页面
driver.get("https://www.baidu.com/")
time.sleep(1)
driver.find_element_by_id("kw").send_keys('python')
time.sleep(1)
driver.find_element_by_id('su').click()
time.sleep(1)
# 通过js打开第二个标签页
js = 'window.open("http://www.sougou.com/");'
driver.execute_script(js)
time.sleep(3)
# 获取当前所有窗口
windows = driver.window_handles
print(windows)
time.sleep(2)
# 根据窗口进行切换
driver.switch_to.window(windows[0])
time.sleep(2)
driver.switch_to.window(windows[1])
time.sleep(6)
# 退出
driver.quit()
iframe是html中常用的一种技术, 即一个页面中嵌套了另一个页面, selenium默认是访问不了frame中的内容的, 对应的解决思路是: driver.switch_to.frame()
在使用selenium登良路QQ邮箱的过程中, 会发现无法在邮箱登录input标签中输入内容,通过观察源码可以发现, from表单在一个frame中,所以需要切换到frame中
login_frame = driver.find_element_by_id('login_frame') # 定位到frame
driver.switch_to.frame(login_frame) # 转向到该frame中
模拟登录QQ邮箱:
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
mail_url = "https://mail.qq.com/cgi-bin/loginpage"
driver.get(mail_url)
time.sleep(2)
# 根据定位,切换到iframe
login_frame = driver.find_element_by_id('login_frame')
driver.switch_to.frame(login_frame)
driver.find_element_by_link_text("帐号密码登录").click()
# 输入邮箱的账号密码
driver.find_element_by_xpath('//*[@id="u"]').send_keys("117****[email protected]")
driver.find_element_by_xpath('//*[@id="p"]').send_keys("********")
driver.find_element_by_xpath('//*[@id="login_button"]').click()
time.sleep(3)
# 切换到iframe元素的外边
windows = driver.window_handles
driver.switch_to.window(windows[0])
username = driver.find_element_by_xpath('//*[@id="useralias"]').text
print(username)
time.sleep(10)
# 退出
driver.quit()
当触发了某个事件之后,页面出现了弹窗提示,处理这个提示或者获取提示信息方法如下:
driver.switch_to.alert() # 跟frame一样的处理方式!
driver.forward() # 前进
driver.back() # 后退
爬取斗鱼直播平台的所有房间信息:https://www.douyu.com/directory/all
存在下一页时:aria-disabled=“false”
不存在下一页时:aria-disabled=“true”
ps:应该是斗鱼做了反爬, 始终没有得到预期结果
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
# driver = webdriver.PhantomJS(executable_path='/home/worker/Desktop/driver/phantomjs')
# driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
class Douyu:
def __init__(self):
"""初始化数据"""
self.start_url = "https://www.douyu.com/directory/all"
self.driver = driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
self.content_list = []
def get_content_list(self):
"""提取数据"""
time.sleep(5)
li_list = self.driver.find_elements_by_xpath('//ul[@class="layout-Cover-list"]/li')
for li in li_list:
item = {}
item['title'] = li.find_element_by_xpath('//h3[@class="DyListCover-intro"]').text
item['zone'] = li.find_element_by_xpath('//span[@class="DyListCover-zone"]').text
item['anchor'] = li.find_element_by_xpath('//h2[@class="DyListCover-user"]').text
item['watch_num'] = li.find_element_by_xpath('//span[@class="DyListCover-hot"]').text
self.content_list.append(item)
print(item)
# 提取下一页数据
next_url = self.driver.find_element_by_xpath('//li[@title="下一页"]')
if next_url.get_attribute("aria-disabled")=="false":
return next_url
else:
return False
def save_content_list(self):
"""保存content"""
for content in self.content_list:
print(content)
def run(self):
"""运行逻辑"""
self.driver.get(self.start_url)
next_url = self.get_content_list()
while next_url:
next_url.click()
time.sleep(3)
next_url = self.get_content_list()
# self.save_content_list()
self.driver.close()
if __name__ == "__main__":
douyu = Douyu()
douyu.run()
ps: 有看出问题的同学,欢迎留言(笑哭)…
完成网易云音乐的所有列表名字和url地址
地址: http://music.163.com/#/discover/playlist
# coding=utf-8
from selenium import webdriver
import time
# 指定driver的绝对路径
# driver = webdriver.PhantomJS(executable_path='/home/worker/Desktop/driver/phantomjs')
# driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
class CloudMusic(object):
def __init__(self, *args, **kwargs):
self.start_url = 'http://music.163.com/#/discover/playlist'
self.driver = webdriver.Chrome(executable_path=r'F:\学习\python学习内容\python练习\02_selenium的使用\chromedriver_win32\chromedriver.exe')
def get_content_list(self):
"""提取数据"""
# 切换进iframe
data_frame = self.driver.find_element_by_id('g_iframe')
self.driver.switch_to.frame(data_frame)
# 获取数据
li_list = self.driver.find_elements_by_xpath('//*[@id="m-pl-container"]/li')
print(f"该页有歌单:{len(li_list)}")
content_list = []
for li in li_list:
item = {}
item['title'] = li.find_element_by_class_name('msk').get_attribute("title")
item['href'] = li.find_element_by_class_name('msk').get_attribute("href")
print(item)
content_list.append(item)
# 下一页
page_url_list = self.driver.find_elements_by_xpath('.//div[@class="u-page"]/a')
next_url = page_url_list[-1] if page_url_list[-1].get_attribute("class") != "zbtn znxt js-disabled" else None
return content_list, next_url
def save_content_list(self, content_list):
for content in content_list:
print(content)
def run(self):
"""实现主逻辑"""
# 请求首页面
self.driver.get(self.start_url)
time.sleep(3)
# 获取数据
contemt_list, next_url = self.get_content_list()
# 请求下一页
while next_url is not None:
js = 'window.scrollTo(0,document.body.scrollHeight)' # js语句:滚动到页面最底部
self.driver.execute_script(js) # 执行js的方法
print(next_url.get_attribute('href'))
next_url.click() #页面没有完全加载完,会报错
time.sleep(3)
# 此时在iframe标签中 代码逻辑需要我们先切出
windows = self.driver.window_handles
self.driver.switch_to.window(windows[0])
content_list, next_url = self.get_content_list()
self.save_content_list(content_list)
# 保存逻辑
# self.save_content_list(content_list)
# 退出浏览器
self.driver.quit()
if __name__ == "__main__":
cloudmusic = CloudMusic()
cloudmusic.run()