任务目标

  • 在获取了网页的HTML代码后我们可以使用很多方法查找元素并爬取其中的数据
  • Selenium支持XPath、CSS等多种查找元素的方法,掌握这些方法可以灵活地爬取到所要的数据
  • 这个项目我们学习怎么样使用Selenium的XPath、CSS 等方法查找元素数据。

Selenium 提取HTML元素函数/方法

函数/方法

功能描述

find_element_by_xpath(xpath)

find_elements_by_xpath(xpath)

通过xpath定位元素

find_element_by_id(id)    无find_elements_by_id(id)

通过id定位元素

find_element_by_name(value)

通过name定位元素

find_element_by_css_selector(css)

通过css定位元素

find_element_by_tag_name("tag_name_vaule")

通过tag_name定位元素

find_element_by_class_name("class_name")

通过class_name定位元素

find_element_by_link_text("text_vaule")

find_element_by_partial_link_text()

通过link定位元素

通过部分link内容定位元素

WebElement.text

WebElement. get_attribute(attrName)

查找元素的文本

查找元素的属性

注:上面的类似: 

旧版本selenium格式:find_element_by_xpath(xpath) 

新版本selenium格式:find_element(By.XPATH, xpath)


1. 使用XPath查找元素

(1) 函数 find_element_by_xpath(xpath):查找 xpath 匹配的第一个元素,如果找到就返回一个 WebElement 类型的对象,如果找不到就抛出异常

(2) 函数 find_elements_by_xpath(xpath):查找xpath匹配的所有元素组成的列表,每个元素都是一个 WebElement 对象 ,如果找不到就返回空列表

(3) 任何一个 WebElement 对象都可以调用 find_element_by_xpath 与find_elements_by_xpath 函数。

2. 使用id查找元素

函数 driver.find_element_by_id(id) 查找id编号的第一个元素,如果查找到就返回一个 WebElement 对象,如果没有找到就抛出异常

3. 使用name查找元素

(1)函数 find_element_by_name(value):查找 name=value 匹配的第一个元素,如果找到就返回一个 WebElement 类型的对象,如果找不到就抛出异常;

(2)函数find_elements_by_name(value):查找 name=value匹配的所有元素组成的列表,每个 元素都是一个WebElement对象,如果找不到就返回空列表;

4. 使用CSS查找元素

(1)函数 find_element_by_css_selector(css):查找 css 匹配的第一个元素,如果找到就返回一个 WebElement 类型的对象,如果找不到就抛出异常;

(2)函数 find_elements_by_css_selector(css): 查找css匹配的所有元素组成的列表,每个元素都是一个 WebElement 对象,如果找不到就返回空列表;

5. 使用tag name查找元素

函数 find_elements_by_tag_name(tagName):查找 tagName 匹配的所有元素,如果找到就返回一个 WebElement 列表,如果找不到列表为空。

6. 使用class查找元素

(1)函数 find_element_by_class_name(value) 查找第一个class=value的元素,如果找到就返回该元素的 WebElement 对象,如果找不到就抛出异常。

(2)函数find_elements_by_class_name(value) 查找所有class=value元素,如果找到就返 WebElement列表,如果找不到列表为空。

7. 使用文本查找超级链接

(1)函数 find_element_by_link_text(text) 查找第一个文本值为text 的超级链接元素<a>,如果找到就返回该元素的 WebElement 对象 ,如果找不到就抛出异常。

(2)函数find_element_by_partial_link_text(text) 查找第一个文本值包含text的超级链接元素<a>,如果找到就返回该元素的 WebElement 对象,如果找不到就抛出异常。

(3)函数 find_elements_by_link_text(text) 查找所有文本值为text 的超级链接元素<a>,如果找到就返WebElement列表,如果找不 到列表为空。

(4)函数 find_elements_by_partial_link_text(text) 查找所有文本值 包含text的超级链接元素<a>,果找到就返WebElement列表,如 果找不到列表为空。

8. 查找元素的文本与属性

(1) 任何一个 WebElement 对象都可以通过text属性获取它的文本,元素的文本值是它与它 的所有子孙节点的文字的组合,如果没有就返回空字符串。

(2) 任何一个 WebElement 对象都可以通过 get_attribute(attrName) 获取名称为attrName的属性值,如果元素没有 attrName 属性就返回 None。


实例-网页源码-phone.html

<html>
 <head>
  <style>
    .pic {
        display:inline-block;
        width:200px; 
        vertical-align:top;
        margin:10px;
    }
    .info {
        display:inline-block; 
        width:500px;
    }
    .price { 
        margin: 10px;
        color:red; 
    } 
    h3 {
        display:inline-block;
    }
    .pl {
        color:#888;
    }
  </style>
 </head>
 <body>
  <div>
   <div class="pic">
    <img id="image" src="/images/000001.jpg" width="200"/>
   </div>
   <div class="info">   
    <div class="title">
        <h3 id="title" style="display:inline-block">荣耀 9i</h3>
    </div>
    <div class="mark">
        <span class="pl">品牌</span>:
        <span name="mark">华为</span>
    </div>
    <div class="date">
        <span class="pl">生产日期</span>:
        <span name="date">2016-12-01</span>
    </div>
    <div class="price">
        <span class="pl">价格</span>:
        <span name="price">¥1200.00</span>
    </div>
    <div>简介:</div>
    <div class="detail">
        荣耀 9i 4GB+64GB 幻夜黑
        <a href="#">移动联通</a>
        电信 4G 全面屏手机
        <a href="#">双卡双待</a>
    </div>
   </div>
  </div>
</body>
</html>

实例 Test公共部分如下:

import os
from selenium import webdriver
from selenium.webdriver.common.by import By

driver = webdriver.Chrome()  # 启动chromedriver

# 获取HTML文件的绝对路径
file_path = os.path.abspath('phone.html')  # 注:这里的phone.html必须和python程序在同一个目录下才可以使用abspath
# print(file_path)  # D:..\案例代码\5_3 Selenium查找HTML元素\phone.html

# 用get打开本地HTML文件
driver.get(f'file:///{file_path}')  # 注:这里必须使用绝对路径,∴ os.path.abspath()

# 查找元素如下⬇:

查找元素如下⬇:

# 1.查找网页元素<h3>
elem = driver.find_element(By.XPATH, "//div[@class='info']//h3")
print(type(elem))  
# 运行结果:
# <class 'selenium.webdriver.remote.webelement.WebElement'>
# 2. 查找网页中元素<h4>
try:
    elem = driver.find_element(By.XPATH, "//div[@class='info']//h4")
    print(type(elem))
except Exception as err:
    print(err)
# 运行结果:
# Message: no such element: Unable to locate element: 
# {"method":"xpath","selector":"//div[@class='info']//h4"}
# 3. 查找网页中第一个<span>元素的文本
print(driver.find_element(By.XPATH, "//div[@class='info']//span").text)
# 运行结果:
# 品牌
# 4. 查找网页中<div class='mark'>中所有<span>元素的文本
elem = driver.find_element(By.XPATH, "//div[@class='mark']")
elems = elem.find_elements(By.XPATH, ".//span")
for elem in elems:
    print(elem.text)
# 运行结果:
# 品牌
# 华为
# 5. 查找网页中手机的品牌
print(driver.find_element(By.XPATH, "//div[@class='info']//span[@name='mark']").text)
# 运行结果:
# 华为
# 6. 查找网页中手机图像<img>的地址
print(driver.find_element(By.XPATH, "//div[@class='pic']//img").get_attribute("src"))
# 运行结果:
# file:///D:/images/000001.jpg
# 7. 查找网页中手机图像<img>的 alt 属性与 xxx 属性
elem = driver.find_element(By.XPATH, "//div[@class='pic']//img").get_attribute("alt")
print(type(elem), len(elem))
elem = driver.find_element(By.XPATH, "//div[@class='pic']//img").get_attribute("xxx")
print(elem)
# 运行结果:
# <class 'str'> 0
# None
# 值得注意的是<img>默认有 alt  属性,只是这个网页中没有设置,
# 因此获取的 alt  属性值是空字符串,但是<img>默认没有 xxx 属性,因此得到 None。
# 8. 查找网页中<div class='mark'>的 HTML 文本
elem = driver.find_element(By.XPATH, "//div[@class='mark']")
print("innerHTML")
print(elem.get_attribute("innerHTML").strip())
print("outerHTML")
print(elem.get_attribute("outerHTML").strip())
# 运行结果:
# innerHTML
# <span class="pl">品牌</span>:
#         <span name="mark">华为</span>
# outerHTML
# <div class="mark">
#         <span class="pl">品牌</span>:
#         <span name="mark">华为</span>
#     </div>
# 9. 查找网页中 id="title"的元素文本
print(driver.find_element(By.ID, "title").text)
# 运行结果:
# 荣耀 9i
# 10. 查找网页中 id="name"的元素
try:
    print(driver.find_element(By.ID, "name"))
except Exception as err:
    print(err)
# 运行结果:
# Message: no such element: Unable to locate element: 
# {"method":"css selector","selector":"[id="name"]"}
# 11. 找网页中手机品牌
print(driver.find_element(By.NAME, "mark").text)
# 运行结果:
# 华为
# 12. 查找网页 name="xxx"的元素
try:
    driver.find_element(By.NAME, "xxx")
except Exception as err:
    print(err)
# 运行结果:
# Message: no such element: Unable to locate element: 
# {"method":"css selector","selector":"[name="xxx"]"}
# 13. 查找网页中手机品牌
print(driver.find_element(By.CSS_SELECTOR, "div[class='info'] span[name='mark']").text)
# 运行结果:
# 华为
# 14. 查找网页中手机图像地址
print(driver.find_element(By.CSS_SELECTOR, "div[class='pic']>img").get_attribute("src"))
# 运行结果:
# file:///D:/images/000001.jpg
# 15. 查找网页中<div class='mark'>下面的所有元素
elems = driver.find_elements(By.CSS_SELECTOR, "div[class='mark'] *")
for elem in elems:
    print(elem.text)
# 运行结果:
# 品牌
# 华为
# 16. 查找网页中手机型号
print(driver.find_element(By.CSS_SELECTOR, "#title").text)
# 或者:
print(driver.find_element(By.CSS_SELECTOR, "[id='title']").text)
# 运行结果:
# 荣耀 9i
# 17. 查找<div class='mark'>元素下面的所有<span>元素
elem = driver.find_element(By.XPATH, "//div[@class='mark']")
elems = elem.find_elements(By.TAG_NAME, "span")
for elem in elems:
    print(elem.text)
# 运行结果:
# 品牌 
# 华为
# 18. 查找网页中手机型号
print(driver.find_element(By.TAG_NAME, "h3").text)
# 运行结果:
# 荣耀 9i
# 19. 查找网页 class="pl"的所有元素
elems = driver.find_elements(By.CLASS_NAME, "pl")
# 或者:
elems = driver.find_elements(By.XPATH, "//*[@class='pl']")
# 或者:
elems = driver.find_elements(By.CSS_SELECTOR, "*[class='pl']")
for elem in elems:
    print(elem.text)
# 运行结果:
# 品牌
# 生产日期
# 价格
# 20. 查找网页<a href="#">移动联通<a>元素
print(driver.find_element(By.XPATH, "//div[@class='detail']/a").text)
print(driver.find_element(By.LINK_TEXT, "移动联通").text)
print(driver.find_element(By.PARTIAL_LINK_TEXT, "移动").text)
print(driver.find_element(By.PARTIAL_LINK_TEXT, "动联").text)
# 运行结果:
# 移动联通
# 移动联通
# 移动联通
# 移动联通

# print(driver.find_element(By.LINK_TEXT, "移动").text)
# 找不到的,因为这个函数要求文本要完全匹配。

 下一篇文章:5.4 Selenium 实现用户登录