xpath

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)

posted @ 2022-05-20 16:42  沈忻凯  阅读(71)  评论(0)    收藏  举报