day 6-xpath数据解析学习总结

day 6-xpath数据解析

1.爬商品详情页数据

import requests
from bs4 import BeautifulSoup
import time, csv
from selenium.webdriver import Chrome, ChromeOptions
from re import fullmatch
headers = {
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'
}

# 获取商品列表中商品的地址
def get_one_page(page, word='电脑'):
    """
    获取一页商品的详情的地址
    :param page: 页数
    :param word: 商品名称
    :return: 一页所有商品的详情地址
    """
    # 获取网页数据
    url = fr'https://search.jd.com/Search?keyword={word}&wq={word}&pvid=6a665414b72a4b43be6f7e15ec7680dd&page={page}&s={page*30+1}&click=0'
    response = requests.get(url, headers=headers)
    # 解析数据,拿到每个商品的详情地址
    soup = BeautifulSoup(response.text, 'lxml')
    goods_li = soup.select('#J_goodsList>ul>li')
    all_data = []
    for li in goods_li:
        goods_url = 'https:'+li.select_one('.p-name>a').attrs['href']
        # print(goods_url)
        all_data.append(goods_url)
    return all_data



# 通过selenium获取一个商品的详细信息
options = ChromeOptions()
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})
b = Chrome(options=options)
b.implicitly_wait(3)


def get_goods_details(goods_url):
    """获取商品详情数据"""
    # 1. 打开详情页
    b.get(goods_url)
    # 2.滚动到商品评价按钮对应的位置
    for _ in range(3):
        b.execute_script('window.scrollBy(0, 500)')
        time.sleep(1)

    # 3.点击商品评价按钮
    b.find_element_by_css_selector('#detail>div>ul>li:nth-child(5)').click()
    # 4. 等2秒
    time.sleep(2)
    # 5. 获取网页源代码做解析
    soup = BeautifulSoup(b.page_source, 'lxml')

    # 1)获取商品信息
    info_lis = soup.select('.parameter2>li')
    goods_data = {}
    for li in info_lis:
        text = li.text              # type: str
        key, value = text.split(':')
        goods_data[key] = value

    # 2)获取评论信息
    comment_as = soup.select('.filter-list>li>a')
    comment_data = {}
    for a in comment_as:
        text = a.text     # type: str
        print(text)
        result = fullmatch(r'(.+)\((.*)\)', text)
        goods_data[result.group(1)] = result.group(2)

    # goods_data['comment'] = comment_data

    writer.writerow(list(goods_data.values()))
    print('------------------------------------保存成功-----------------------------------')


if __name__ == '__main__':
    f = open('files/电脑商品信息.csv', 'a', encoding='utf-8', newline='')
    writer = csv.writer(f)

    for page in range(1, 6):
        goods_url_list = get_one_page(page)

        for i in goods_url_list:
            get_goods_details(i)
        time.sleep(1)

2.xpath语法

1.什么是Xpath(xml path 语言)

专门用来解析xml数据

不同的编程语言的程序如果想要进行数据交流,数据传输之前必须转换成通用的数据格式(常用的有两种:json、xml)

Xpath解析数据的原理:通过提供你需要的标签在整个网页(xml)中的路径,来找到对应的标签,进一步获取标签内容或者标签属性。

python基于xpath做数据解析的工具:lxml第三方库

2.xml数据

一种通用的数据格式

xml数据是以标签(元素)为单位,通过标签内容或者标签属性来提供数据。

xml语法:<标签名 属性名1=属性值1 属性名2=属性值2 …>标签内容</标签名>

案例:用json和xml来保存一个订单数据
json版本:
{
    "id": "oder028398923",
    "create_time": "2022-6-26 22:34:56",
    "pay_time": "2022-6-26 22:36:02",
    "goods_list":[
        {"goods_id": "9234233", "price": 123.00, "count": 2, "name": "XXX防晒霜"},
        {"goods_id": "7281911", "price": 32.00, "count": 1, "name": "拖鞋"}
    ]
}

<order id="oder028398923">
    <create_time>2022-6-26 22:34:56</create_time>
    <pay_time>2022-6-26 22:36:02</pay_time>
    <goods_list>
        <goods goods_id="9234233">
            <price>123.00</price>
            <count>2</count>
            <name>XXX防晒霜</name>
        </goods>
            
        <goods goods_id="7281911">
            <price>32.00</price>
            <count>1</count>
            <name>拖鞋</name>
        </goods>
    </goods_list>
</order>

3.xpath常用术语

树: 树结构(一个网页源代码,一个xml数据本质就是一个树结构)

节点: 本质就是标签

根节点: 最外层的哪个标签

节点内容: 双标签标签内容

节点属性: 标签属性

4. xpath语法

1)基于html数据或xml数据创建html或者xml对应的树并且获取根节点

etree.HTML(网页源代码)、etree.XML(xml数据)

f = open('files/超市.xml', encoding='utf-8')
root = etree.XML(f.read())
f.close()
2)基于节点通过路径获取标签

节点对象.xpath(路径) - 根据路径获取对应的标签,返回值是一个列表,列表中的元素是对应的标签对象

路径写法:

1.绝对路径:

​ /路径 (路径必须从根节点开始往后写)

2.相对路径:

​ ./路径 (.表示当前节点; 谁去点的xpath,当前节点就是谁)

​ …/路径 (…表示当前节点的上层节点)

​ 注意:如果路径是以 ‘./’ 开始的,‘./’ 可以省略

3.任意路径:

​ //路径

注意:绝对路径和任意路径,在写路径和获取标签的时候跟xpath前面是哪个标签没有任何关系

# ================绝对路径=============
result = root.xpath('/supermarket/name')
print(result)

result = root.xpath('/supermarket/staffs/staff')
print(result)

# 练习:通过写绝对路径,获取所有商品的商品名对应的标签
result = root.xpath('/supermarket/all_goods/goods/name')
print(result)
# ==============相对路径================
all_goods = root.xpath('./all_goods')[0]

# result = all_goods.xpath('/supermarket/all_goods/goods/name')
# print(result)
result = all_goods.xpath('./goods/name')
print(result)
# ============任意路径==============
result = root.xpath('//name')
print(result)

result = all_goods.xpath('//name')
print(result)

3.xpath语法2

from lxml import etree

root = etree.XML(open('files/超市.xml', encoding='utf-8').read())

1.获取标签内容和标签属性

1)获取标签内容:

获取标签的路径/text()

result = root.xpath('//goods/name/text()')
print(result)       # ['泡面', '火腿肠', '矿泉水', '巧克力']
2)获取标签属性值:

获取标签的路径/@属性名

result = root.xpath('//staff/@position')
print(result)

2. 谓语(条件)

谓语的写法:[谓语]

1) 位置相关谓语

[N] - 第N个标签(N是任意正整数)

[last()] - 获取最后一个标签

[last()-1] - 获取倒数第2个标签。这儿的1可以是其他任意的整数

[position()>N]、 [position()>=N]、[position()<N]、[position()<=N]

result = root.xpath('//goods[2]/name/text()')
print(result)       # ['火腿肠']

result = root.xpath('//goods[last()]/name/text()')
print(result)       # ['巧克力']

result = root.xpath('//goods[last()-1]/name/text()')
print(result)       # ['矿泉水']

result = root.xpath('//goods[position()<=3]/name/text()')
print(result)       # ['泡面', '火腿肠', '矿泉水']
2)属性相关谓语

[@属性名=值] - 获取指定属性为指定值的标签

[@属性名] - 获取拥有指定属性的标签

result = root.xpath('//goods[@class="c3"]/name/text()')
print(result)

result = root.xpath('//goods[@id="d1"]/name/text()')
print(result)


result = root.xpath('//goods[@class]/name/text()')
print(result)
*3)子标签内容相关谓语
[子标签名>值]、[子标签名>=值]、[子标签名<值]、[子标签名<=值]、[子标签名=值]
result = root.xpath('//goods[pirce=1.5]/name/text()')
print(result)

3. 分支 - |

路径1|路径2 - 先通过路径1获取标签,如果获取不到再通过路径2获取(获取的是多个路径中所有有效路径的结果)

result = root.xpath('//goods/name1/text()|//goods/name2/text()')
print(result)       # []

result = root.xpath('//goods/name2/text()|//goods/name/text()')
print(result)       # ['泡面', '火腿肠', '矿泉水', '巧克力']

result = root.xpath('//goods/name/text()|//staffs/staff/text()')
print(result)      # ['张三', '小明', '小红', '小花', '泡面', '火腿肠', '矿泉水', '巧克力']

4.通配符 - *

xpath中可以用*来代表任意标签或者任意属性

result = root.xpath('//goods/name/text()')
print(result)

result = root.xpath('//goods/*/text()')
print(result)       # ['泡面', '3.5', '120', '火腿肠', '1.5', '305', '矿泉水', '1.5', '1200', '巧克力', '11.5', '50']


result = root.xpath('//*[@class="c2"]')
print(result)

# 所有第一个员工的所有属性值
result = root.xpath('//staff[1]/@*')
print(result)

# 获取属性值为c2的所有标签
result = root.xpath('//*[@*="c2"]')
print(result)

# 获取id值为'd1'的标签
result = root.xpath('//*[@id="d1"]')
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值