Selenium模块一
一,安装
-
安装 selenium
pip install selenium
-
安装谷歌浏览器驱动(chromedriver.exe),解压之后移动到 python 解释器的根目录
http://chromedriver.storage.googleapis.com/index.html
注意 :
解压之后是一个 chromedriver.exe 程序,需要移动到 python 解释器的根目录
-
为什么要用 selenium ,能够加载 js 代码,把加密的部分解决了
二,简单使用
-
驱动浏览器
# 创建了一个谷歌浏览器驱动的实例 driver = webdriver.Chrome() # 打开百度官网 driver.get('https://www.baidu.com') # 获取当前页面的源代码,审查页面的元素 print(driver.page_source)
from selenium import webdriver opt = webdriver.ChromeOptions() opt.binary_location = r"D:\All_Work_App\Google\Google\Chrome\Application\chrome.exe" chromedriver_path = 'D:\Python\CREATE_PYTHON_ENV\Spider_env\chromedriver.exe' driver = webdriver.Chrome(executable_path=chromedriver_path, chrome_options=opt) driver.get('https://www.baidu.com') driver.close()
-
定位元素
-
通过 element 定位元素
elem1 = driver.find_element_by_id() elem2 = driver.find_element_by_class_name() elem3 = driver.find_element_by_name() elem4 = driver.find_element_by_link_text() # 通过文字链接定位
-
通过 xpath 定位元素
elem = driver.find_element_by_xpath() # 自行脑补,寻找单个 elem = driver.find_elements_by_xpath() # 寻找多个
-
-
给 input传输框传 输内容
elem.send_keys('hello world') elem.clear() # 清空
-
模拟键盘鼠标操作
如果浏览器加载的过慢,需要进行延时,等待浏览器加载完毕
from selenium.webdriver.common.keys import Keys # 使用回车键进行搜索 elem1 = driver.find_element_by_id('kw') # 定位到 id 为 kw 的元素 elem1.send_keys('hello') # 给input框 传入内容 elem1.send_keys(Keys.ENTER) # 回车搜索 # 鼠标点击按钮 driver.find_element_by_xpath('//input[@id="su"]').click() # 点击搜索 driver.find_element_by_link_text('百度首页').click() # 点击百度首页
-
关闭浏览器
driver.close() # 关闭当前窗口 driver.quit() # 关闭整个浏览器
三,使用 selenium 获取 cookies
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
cooks_data = driver.get_cookies()
cookies = {}
for i in cooks_data:
cookies[i['name']] = i['value']
print(cookies)
time.sleep(2)
driver.quit()
{'H_PS_PSSID': '26523_1427_21101_29523_29521_29098_29567_28832_29221_26350_29460', 'BIDUPSID': 'C9B38FC612177C65DDF523262D9535DB', 'delPer': '0', 'PSTM': '1565774731', 'BDORZ': 'B490B5EBF6F3CD402E515D22BCDA1598', 'BD_UPN': '12314753', 'BD_HOME': '0', 'BAIDUID': 'C9B38FC612177C65DDF523262D9535DB:FG=1'}
四,对于iframe框架窗口处理
QQ空间的窗口需要切换才能定位元素
定位iframe
1.有id,并且唯一,直接写id
driver.switch_to_frame("x-URS-iframe")
driver.switch_to.frame("x-URS-iframe")
2.有name,并且唯一,直接写name
driver.switch_to_frame("xxxx")
driver.switch_to.frame("xxxx")
3.无id,无name,先定位iframe元素
iframe = driver.find_elements_by_tag_name("iframe")[0]
driver.switch_to_frame(iframe)
driver.switch_to.frame(iframe)
================================================
import time
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://qzone.qq.com/')
# 切换 iframe
driver.switch_to_frame('login_frame')
try:
driver.find_element_by_id('switcher_plogin').click()
except Exception as e:
print(e)
finally:
time.sleep(3)
driver.quit()
五,切换窗口句柄
selenium 默认在第一个窗口句柄定位元素,需要 switch 切换窗口
-
查看当前浏览器窗口句柄,切换句柄
# 查看窗口句柄 print(window_handles) # 切换句柄 driver.switch_to_window(driver.window_handles[1])
-
从百度登录 qq 空间
# 窗口处理 import time from selenium import webdriver from selenium.webdriver.common.keys import Keys driver = webdriver.Chrome() driver.get('https://www.baidu.com') elem = driver.find_element_by_id('kw') elem.send_keys('QQ空间') elem.send_keys(Keys.ENTER) time.sleep(2) driver.find_element_by_xpath('//div[@id="content_left"]/div[1]/h3/a').click() # 查看浏览器窗口句柄并切换 print(driver.window_handles) driver.switch_to_window(driver.window_handles[1]) # 切换 iframe driver.switch_to_frame('login_frame') # 点击账号密码登录 driver.find_element_by_id('switcher_plogin').click() # 输入账号密码 driver.find_element_by_id('u').send_keys('xxxxxxx') driver.find_element_by_id('p').send_keys('xxxxxxx') driver.find_element_by_id('login_button').click()
六,弹出窗口处理
js 弹出的窗口我们不能定位,需要switch切换
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
driver.find_element_by_link_text('设置').click()
driver.find_element_by_link_text('搜索设置').click()
time.sleep(1)
driver.find_element_by_link_text('保存设置').click()
time.sleep(1)
alert = driver.switch_to.alert
alert.accept()
七,浏览器前进和后退
driver.back()
driver.forward()
八,元素的拖动
点击一个元素,把其从网页上的一个地方拖拽到另外一个地方
import time
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.get('http://www.treejs.cn/v3/demo/cn/exedit/drag.html')
start = driver.find_element_by_id('treeDemo_2_span')
end = driver.find_element_by_id('treeDemo_14_span')
time.sleep(2)
ActionChains(driver).drag_and_drop(start, end).perform()
九,无头浏览器
性能低,无界面
import time
from selenium import webdriver
opt = webdriver.ChromeOptions()
opt.add_argument('--headless')
driver = webdriver.Chrome(chrome_options=opt)
driver.get('https://www.baidu.com')
print(driver.page_source)
Selenium模块二
一,显示等待和隐示等待
在 JS 和 ajax 加载之前有些按键是不能点击的,需要等待加载完毕
-
显示等待 : 等待某固定的条件满足
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By # 提供判断的方法 from selenium.webdriver.support import expected_conditions as EC wait = WebDriverWait(driver, timeout=20) # timeout是最大超时时间 # presence of element located 判断元素是否加载成功 find = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'search-keyword'))) # 也是相当于做了一次元素定位 find.send_keys('111') # 直接能把定位的元素拿过来用 # text_to_be_present_in_element 判断文本是否出现在元素的text里面 # text_to_be_present_in_element_value 判断value属性 # element_to_be_clickable 判断元素是否可以点击
-
隐示等待 : 等待固定的时间,类似 time.sleep()
driver.implicitly_wait(10) # 在页面加载的时候都等待10秒
三,动作链
-
拖拽,移动,点击,松开
from selenium.webdriver.common.action_chains import ActionChains ActionChains.drag_and_drop 参数:source, target # 拖拽到某个元素,起始和结束 drag_and_drop_by_offset 参数:sourcce, xoffset, yoffset # 拖拽到某个坐标点 # 点击,滑动,松开 elem = self.driver.find_element_by_class_name('gt_slider_knob') ActionChains(self.driver).click_and_hold(elem).perform() ActionChains(self.driver).move_by_offset(xoffset=x, yoffset=0).perform() ActionChains(self.driver).release(elem).perform()
-
截图
# 1. 整个屏幕截图 driver.get('https://www.bilibili.com/') driver.save_screenshot('snap.png') # 2. 定位元素截图 elem = driver.find_element_by_xpath('//*[@id="lg"]/img[1]') elem.screenshot('1.png') # 3. 找出元素的位置,进行图片切割 elem = driver.find_element_by_xpath('//*[@id="lg"]/img[1]') print(elem.location) {'x': 330, 'y': 149} print(elem.size) {'height': 129, 'width': 270}
selenium获取京东数据
- 请求首页
- 定位输入框,输入相对的内容,确定
- 等待元素加载完成获取源码
- 下一页
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
from lxml import etree
class JdSpider():
binary_location = r"D:\All_Work_App\Google\Google\Chrome\Application\chrome.exe"
chromedriver_path = 'D:\Python\CREATE_PYTHON_ENV\Spider_env\chromedriver.exe'
def __init__(self, url):
self.url = url
self.wait = WebDriverWait(self.driver, timeout=10)
self.opt = webdriver.ChromeOptions()
self.opt.binary_location = self.binary_location
self.driver = webdriver.Chrome(executable_path=self.chromedriver_path, chrome_options=self.opt)
def start(self):
self.driver.get(self.url)
def search(self):
# 定位输入框,输入数据
user_input = input('请输入你要爬取的商品:\t')
input_ = self.wait.until(EC.presence_of_element_located((By.ID, 'key')))
input_.send_keys(user_input)
submit = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'button')))
submit.click()
def wait_data(self):
# 等待商品数据加载完成
self.wait.until(EC.presence_of_all_elements_located((By.CLASS_NAME, 'gl-item')))
def parse_and_next(self):
# 延时,加载30条
self.wait_data()
# 滑块下滑,制定js代码,如果不翻页,按钮可能没有加载出来
js = 'window.scrollTo(0, document.body.scrollHeight)'
self.driver.execute_script(js)
# 延时,等待ajax加载的30条完成
time.sleep(3)
# 打印源代码
html = self.driver.page_source
self.parse_html(html)
# 翻页
try:
next = self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'pn-next')))
next.click()
except TimeoutError:
pass
def parse_html(self, response):
selector = etree.HTML(response)
items = selector.xpath('//li[@class="gl-item"]')
for item in items:
print('title : {}'.format(item.xpath('string(.//div[contains(@class, "p-name")]/a/em)')))
print('price : {}'.format(item.xpath('.//div[@class="p-price"]//i/text()')[0]))
print('comment : {}'.format(item.xpath('string(.//div[@class="p-commit"])').strip()))
print('-' * 10)
print('一共加载{}条'.format(len(items)))
if __name__ == '__main__':
JD = JdSpider('https://www.jd.com')
JD.start()
JD.search()
while True:
JD.parse_and_next()