任务目标
- 在获取了网页的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 实现用户登录