python爬虫学习笔记5-xpath

本文重点

  1. xpath helpler
  2. xpath:语言,查取HTML/XML文档中元素。
  3. lxml:解析器。
  4. csv文件的读写

参考文档

XPath Helper

XPath 教程

辅助工具

XPath Helper

此篇文档讲解了如何安装和使用。XPath Helper

在浏览器中的使用流程,右键->检查->点击一个

标签,右键copy->copy xpath,将复制的xpath复制到XPath Helper命令行【快捷键CTRL+SHIFT+X】内。

image-20201214131636175

xpath

此处仅明确几个概念,简单会用即可,详细的参考文档可以看看XPath 教程

概念

节点

每个xml的标签都称为节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点。

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore>

<book>
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author> 
  <year>2005</year>
  <price>29.99</price>
</book>

</bookstore>
<bookstore> (文档节点)
<author>J K. Rowling</author> (元素节点)
lang="en" (属性节点) 

选取节点

XPath 使用路径表达式来选取 XML 文档中的节点或节点集。节点是通过沿着路径 (path) 或者步 (steps) 来选取的。

路径表达式

常用路径表达式

表达式描述
nodename选取此节点的所有子节点。
/从根节点选取。
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
.选取当前节点。
选取当前节点的父节点。
@选取属性。

带谓语的路径表达式

路径表达式结果
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()❤️]选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang=‘eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

lxml

简介

lxml是一个HTML/XML的解析器,主要功能用于解析HTML/XML数据。

lxml中的etree将html字符串转化为element对象,再通过xpath()方法来选取节点。

安装

pip install lxml

官方文档

https://lxml.de/index.html

lxml的简单应用

from lxml import etree
"""
etree的作用
第⼀个是将html字符串转化为element对象
第⼆个是element对象可以转换为字符串或者⼆进制类型
"""
wb_data = """
        <div>
            <ul>
                 <li class="item-0"><a href="link1.html">first item</a></li>
                 <li class="item-1"><a href="link2.html">second item</a></li>
                 <li class="item-inactive"><a href="link3.html">third item</a></li>
                 <li class="item-1"><a href="link4.html">fourth item</a></li>
                 <li class="item-0"><a href="link5.html">fifth item</a>
             </ul>
         </div>
        """
#html字符串转化为element对象
html_element = etree.HTML(wb_data)
#<Element html at 0x20ea63304c0>
# print(html_element)
#<class 'lxml.etree._Element'>
# print(type(html_element))

# result = etree.tostring(html_element)
# r = result.decode()
# print(type(r),r)

# 获取所有<li>标签下面<a>标签的href属性
links=html_element.xpath('//li/a/@href')
# print(links)
# 获取<a>标签下的文本数据
results=html_element.xpath('//li/a/text()')
# print(results)

# {'href': 'link1.html', 'title': 'first item'}
for link in links:
    d={}
    d['href']=link
    # print(links.index(link))
    d['title']=results[links.index(link)]
    print(d)

csv的读写

csv(字符分隔值,常用的是逗号分隔值),常用的文本格式,用以存储表格数据,包括数字或者字符。python自带csv模块,专门用于处理csv文件的读取。下面代码是csv的简单应用。

"""
@FileName:csv的读写.py
@Description:
@Author:lmz
@Time:2020/12/14 14:57
"""
"""
需求:读取persons.csv的内容

步骤:
1.导入csv库

# 读取csv文件
2.打开persons.csv
with open('filename.csv','r|w',encoding='utf-8',newline='') as f:
3.读取文件内容方法
    - csv.DictReader
    - csv.reader
    
# csv写入文件
    - csv.DictWriter(f,titles)
        - writer.writeheader(titles)# 写入标题
        - writer.writerows(rows) # 写入所有行
    - csv.writer()
        - writer.writerow(titles)
        - writer.writerows(rows)
"""

# csv读取文件
import csv
# 第一种
with open('persons.csv','r',encoding='utf-8') as f:
    reader=csv.reader(f)
    print(type(reader),reader)
    for i in reader: # 按行遍历
        print(i[2])# [开始下标是0,第2列]

# 第二种
# 打开文件作为f,解码格式是utf-8
# with open('persons.csv','r',encoding='utf-8') as f:
#     reader=csv.DictReader(f)
#     # print(type(reader),reader)
#     for i in reader:
#         print(i['name'])


# csv写入文件
titles = ('name','age','height')
persons = [('张三',20,175),('李四',22,178),('王五',30,180)]
# 第一种
# 问题:每2行中间会有一个空行
# with open('person1.csv','w',encoding='utf-8') as f:
#     writer = csv.writer(f)  # 写入到文件f
#     writer.writerow(titles)# 写入行
#     for data in persons:
#         writer.writerow(data)

# 换行为'',解决了问题:每2行中间会有一个空行
# with open('person2.csv','w',encoding='utf-8',newline='') as f:
#     writer = csv.writer(f)
#     writer.writerow(titles)
#     writer.writerows(persons)# 写入所有行

# 第二种
person = [
    {'name':'张三','age':20,'height':175},
    {'name':'李四','age':22,'height':178},
    {'name':'王五','age':30,'height':180}
]

with open('person3.csv','w',encoding='utf-8',newline='') as f:
    writer = csv.DictWriter(f,titles) # 传入待写入文件和标题
    writer.writeheader()# 写入标题
    writer.writerows(person) # 写入所有行

豆瓣

此案例是对requests、lxml、csv的一个结合使用。

requests:获取网页源码

lxml:解析数据

csv:保存数据

"""
@FileName:豆瓣.py
@Description:
@Author:lmz
@Time:2020/12/14 17:05
"""
import requests
from lxml import etree
import csv
"""
需求:
爬取每部电影的名字 评分 引言 详情页的url 10页 把这些数据保存到csv文件当中

走一遍流程,查看url进行总结
# https://movie.douban.com/top250?start=0&filter=  第一页
# https://movie.douban.com/top250?start=25&filter= 第二页
# https://movie.douban.com/top250?start=50&filter= 第三页
# https://movie.douban.com/top250?start=75&filter= 第四页
# 规律 (page-1)*25

使用xpath对下面节点进行解析
![image-20201214183309894](https://yanyunpo-oss.oss-cn-shanghai.aliyuncs.com/img/image-20201214183309894.png)

步骤:
1. 获取网页源码
2. 解析数据 电影的名字 评分 引言 详情页的url
3. 保存数据
"""

doubanurl='https://movie.douban.com/top250?start={}&filter='

# 获取网页源码
def getSource(url):
    headers={
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36'
    }
    response = requests.get(url,headers=headers)
    response.encoding='utf-8'
    return response.text
# 解析数据 电影的名字 评分 引言 详情页的url
def getEveryItem(source):
    html_element = etree.HTML(source)
    movieItemlist = html_element.xpath('//div[@class="info"]')
    # 保存字典数据
    movieList = []

    for eachMoive in movieItemlist:
        # 保存电影详情数据
        movieDict = {}
        title = eachMoive.xpath('div[@class="hd"]/a/span[@class="title"]/text()') # 标题
        otherTitle = eachMoive.xpath('div[@class="hd"]/a/span[@class="other"]/text()')  # 副标题
        link = eachMoive.xpath('div[@class="hd"]/a/@href')[0]  # 详情页的url
        star = eachMoive.xpath('div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()')[0] # 评分
        quote = eachMoive.xpath('div[@class="bd"]/p[@class="quote"]/span/text()') # 引言(名句)
        # 处理格式问题
        if quote:
            quote = quote[0]
        else:
            quote = ''

        movieDict['title'] = ''.join(title + otherTitle)
        movieDict['url'] = link
        movieDict['star'] = star
        movieDict['quote'] = quote

        movieList.append(movieDict)

        # print(movieList)

    return movieList


# 保存数据
def writeData(movieList):
    with open('douban.csv', 'w', encoding='utf-8', newline='') as f:

        writer = csv.DictWriter(f,fieldnames=['title','star','quote','url'])
        writer.writeheader()

        for each in movieList:
            writer.writerow(each)

# 执行程序
if __name__ == '__main__':
    movielist=[]

    for i in range(10):
        # 获取每一页的url
        pageLink=doubanurl.format(i*25)
        # print(pageLink)
        # 获取每一页的源码
        source = getSource(pageLink)
        # print(source)
        # 解析数据 movieList = movieList + getEveryItem(source)
        movielist += getEveryItem(source)
        # print(movielist)

    # 写入数据 csv
    writeData(movielist)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值