1.xpath方法
1.1 安装
pip install lxml
1.2 etree.HTML(页面源代码)
page = etree.HTML(content) # type: etree._Element # 给pycharm看的 # 默认pycharm不知道什么类型. 没有代码提示
# 以后写代码. 没提示怎么办?
# 用type() 得到数据类型.
# 去变量被赋值位置, 添加 # type: 类型
2.xpath基础语法
# / 出现在开头. 表示根节点,xpath得到的结果永远永远是列表
root = page.xpath("/html") # [<Element xxx at xxx>]
print(type(root))
# / 出现在中间 直接子节点
p = page.xpath("/html/body/div/p")
print(p)
# / 出现在中间 也有可能是找某个节点内部的东西
# text() 提取内部的文本
s = page.xpath("/html/body/div/p/text()") # 拿到的文本是[]
print(s) # 返回列表
# // 出现在后代节点,跨标签提取
s = page.xpath("/html/body/div/p//text()")
print(s)
# // 查找所有子节点 /p 所有子节点中的p
divs = page.xpath("//div/p/text()")
print(divs)
# 在xpath里 [] 里面可以给出位置. 位置是从1开始数的
zi = page.xpath("//ol/ol/li[2]/text()")
print(zi)
# li[3] 表示 上层标签中第三个li
r = page.xpath("//li[3]/text()")
print(r)
3.xpath高级方法
# xpath语法中 @属性,属性上的限定
# 这里写属性选择的时候. 直接复制即可(页面源代码).
z = page.xpath("//ol/li[@id='10086']/text()")
print(z)
# * 单个任意标签
# * 在这里表示任意节点
x = page.xpath("//*[@ygl='skt']/text()")
print(x)
# 在这里表示div标签下一层任意标签
z = page.xpath("//div/*/span/text()")
print(z)
# 网页中拿到ul中每一个href
# @href 拿href的值
# 方案一 直接拿取
href = page.xpath("//ul/li/a/@href")
for h in href:
print(h)
# 后续的操作。和该页面没有其他关系了
# 此时直接拿href没问题!!
# 方案二 可扩展性更好一些。
a_list = page.xpath("//ul/li/a")
for a in a_list:
href = a.xpath("./@href")[0]
txt_lst = a.xpath("./text()")
if txt_lst: # 判断
txt = txt_lst[0]
else:
txt = ""
# 需要把文字和href写入文件
print(txt, href) # index out of range
# last() 最后一个
li = page.xpath("//ol/li[last()]/a/@href")
print(li)
4.案例一(漫品狗)
import requests
from lxml import etree
from urllib.parse import urljoin
import time
url = 'https://www.manpingou.com/coin/list.php?tid=79&TotalResult=2567&PageNo=1'
urls = 'https://www.manpingou.com'
header = {
"user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.88 Safari/537.36"
}
resp = requests.get(url, headers=header)
resp_text = resp.text
# print(resp_text)
# 获取首页url
xpath_text = etree.HTML(resp_text) # type: etree._Element
xpath_list = xpath_text.xpath("//div[@class='image-list clearfix']//a[1]") # type: etree._Element
for a in xpath_list:
href = a.xpath('./@href')[0]
# print(href)
# 获取详情页
resps = requests.get(href, headers=header)
resps_list = resps.text
# print(resps_list)
xpaths_text = etree.HTML(resps_list)
xpaths_list = xpaths_text.xpath("//div[@class='con-view fl']//div/img[1]")
for i in xpaths_list:
hrefs = i.xpath("./@src")[0]
# print(hrefs)
url_src = urljoin(urls, hrefs)
if url_src.endswith('lp.jpg'):
continue
print(url_src)
# 下载图片
xiazai = requests.get(url_src, headers=header)
file_name = url_src.split("/")[-1]
with open(f'ty/{file_name}', 'wb') as w:
w.write(xiazai.content)
time.sleep(0.5)
5.案例二(中国电影排名)
import requests
from lxml import etree
# 1.拿页面源代码#
# 2.xpath提取数据
# //table/tbody/tr
url = "http://www.boxofficecn.com/boxoffice2022"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.84 Safari/537.36"
}
resp = requests.get(url, headers=headers)
# print(resp.text)
page = etree.HTML(resp.text)
trs = page.xpath("//table/tbody/tr")[1:-1]
# tr全是数据
for tr in trs:
num = tr.xpath("./td[1]/text()")
year = tr.xpath("./td[2]//text()")
name = tr.xpath("./td[3]//text()")[0]
# py基础
if name:
"".join(name) # 这是合理的方案
money = tr.xpath("./td[4]/text()")
print(num, year, name, money)
# 不正常
movie1 = ['京北的我们(', '重映', ')'] # 京北的我们(重映)
len(movie1) # ???? 3
# 正常的 1
movie2 = ['不要忘记我爱你']
# 这个是空
movie3 = []
6.案例三(学校PDF)
import requests
from lxml import etree
import os
url = 'https://gs.sufe.edu.cn/Home/Promulgate'
header = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36'
}
# 确保pdf文件夹存在
os.makedirs('pdf', exist_ok=True)
# 获取页面源代码
r = requests.get(url, headers=header)
r.raise_for_status() # 如果请求失败,将引发HTTPError异常
# xapth 解析
tree = etree.HTML(r.text)
trs = tree.xpath('//div[@class="conn content-main"]/*//span')
# 循环取出下载url
for tr in trs:
href = tr.xpath('./a[2]/@href')
text = tr.xpath('./a[1]/text()')
# 获取文件名称并清理(如果需要)
file_name = text[0].strip().replace('/', '_') if text else 'unknown'
file_pdf = f'pdf/{file_name}.pdf'
# 判断是否为空
if href:
print(href[0], file_pdf)
# 下载pdf
pdf_response = requests.get(href[0])
pdf_response.raise_for_status() # 如果请求失败,将引发HTTPError异常
with open(file_pdf, 'wb') as w:
w.write(pdf_response.content)