美文网首页
数据解析-Xpath

数据解析-Xpath

作者: 逍遥_yjz | 来源:发表于2021-06-10 08:11 被阅读0次

1. xpath安装及基本语法

环境的安装:pip install lxml
  • 1.xpath的解析原理
    实例化一个etree类型的对象,且将页面源码数据加载到该对象中
    需要调用该对象的xpath方法结合着不同形式的xpath表达式进行标签定位和数据提取

  • 2.etree对象的实例化
    etree.parse(fileNane) #本地的html文件
    etree.HTML(page_text) #声明了一段HTML文本,调用HTML类进行初始化,构造了一个XPath解析对象
    xpath方法返回的永远是一个列表

      实例化报错:爬虫中lxml.etree.XMLSyntaxError问题
    

解决方法:
修改代码如下:

1. 解析本地的HTML源码文件,假设其为:XX.html,根据实际更改。
parser = etree.HTMLParser(encoding="utf-8")
tree = etree.parse('XX.html', parser=parser)

2. 解析从互联网获取的HTML源码数据。
page_text = requests.get(url, headers).text
parser = etree.HTMLParser(encoding="utf-8")
tree = etree.HTML(page_text, parser=parser)
  • 3.标签定位
    xpath表达式中最最侧的/表示的含义是说,当前定位的标签必须从根节点开始进行定位
    xpath表达式中最左侧的//表示可以从任意位置进行标签定位
    xpath表达式中非最左侧的//表示的是多个层级的意思
    xpath表达式中非最左侧的/表示的是一个层级的意思

  • 4.属性定位
    //标签名[@arrtName='value']
    循环中标签定位: ./表示当前标签
    索引定位://标签名/li[3] #第三个li标签

    1. 提取数据
    • 5.1取文本:
      /text():取直系的文本内容
      //text():取所有的文本内容,循环中不能再用索引,例如文本中有br标签分割
    • 5.2取属性:
      tag/@attrName
举例:      
from lxml import etree
tree = etree.parse('./test.html')
tree.xpath('/html/head/meta')[0] #绝对路径
tree.xpath('//meta')[0] #相对路径,将整个页面源码中所有的meta进行定位
tree.xpath('/html//meta')[0] 

#属性定位
tree.xpath('//div[@class="song"]')

#索引定位
tree.xpath('//div[@class="tang"]/ul/li[3]') #该索引是从1开始
tree.xpath('//div[@class="tang"]//li[3]') #该索引是从1开始

#取文本
tree.xpath('//p[1]/text()')
tree.xpath('//div[@class="song"]//text()')

#取属性
tree.xpath('//a[@id="feng"]/@href')

2. xpath表达式语法

2.1 使用/表示搜索层级

起始的/表示根节点

/放在首位的时候,表示从根节点开始定位。

后续的/表示层级(bs4的>)
from lxml import etree
# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')

# 第一个斜杠表示从根节点开始遍历的
# 后续的斜杠表示层级递进
# 返回值为所有符合表达式规则的属性对象,使用text获取文本内容
tree.xpath('/html/body/title')[0].text

//表示跨越层级(bs4的)

from lxml import etree
# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')
# 第一个斜杠表示从根节点开始遍历的
tree.xpath('//title')

./表示从当前层级往下走

from lxml import etree
# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')
# 第一个斜杠表示从根节点开始遍历的
body = tree.xpath('//body')[0]

# 从body往下走
title = body.xpath('./title')[0]
print(title.text)

# 以下代码直接报错,因为/是从根节点开始的,不是从body开始的
title = body.xpath('/title')[0]
print(title.text)

output >> IndexError: list index out of range

2.2 定位

定位分为两种,一种是属性定位,一种是索引定位。两种方法结合使用会更加精确。

2.2.1 属性定位

语法tag[@attrName="attrValue"]

from lxml import etree

# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')

# 使用类名精确定位p标签
tree.xpath('/html/body/p[@class="story"]')

# 得到符合要求的列表
output >> [<Element p at 0x1c442ae1ac8>, <Element p at 0x1c442ae1e88>]

2.2.2 索引定位

索引定位就是在之前的选择器中多加入了一个索引,2.2.2.1的代码修改为下列代码

from lxml import etree

# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')

# 使用下标精准索引某一标签
tree.xpath('/html/body/p[@class="story"][1]')

# 得到符合要求的列表
output >> <Element p at 0x1c442ae1ac8>

注意,这里的索引下标是从1开始的,而不是从0开始

2.3 输出

  • 在上面的选择器后面加入/text()输出当前标签的文本内容
  • 加入//text()输出所有子标签的内容
from lxml import etree

# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')

# 使用text()打印输出
tree.xpath('/html/body/p[@class="story"]/text()')

# 得到文本内容
output >> ['Once upon a time there were three little sisters; and their names were\n        ',
 ',\n        ',
 ' and\n        ',
 '; and they lived at the bottom of a well.',
 '...']

可以观察到,所有在a标签中的内容都没有打印出来

在使用//text()后,就可以打印出a标签的内容了

from lxml import etree

# 实例化好了一个etree对象,且将被解析的源码加载到了该对象中
tree = etree.parse('alice.html')

# 使用text()打印输出
tree.xpath('/html/body/p[@class="story"]//text()')

# 得到全部文本内容
output >> ['Once upon a time there were three little sisters; and their names were\n        ',
 'Elsie',
 ',\n        ',
 'Lacie',
 ' and\n        ',
 'Tillie',
 '; and they lived at the bottom of a well.',
 '...']

3. demo

爬取糗事百科的段子内容和作者名称

# coding:utf-8
import requests

from lxml import etree
headers = {
    'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
}
url = 'https://www.qiushibaike.com/text/page/4/'
page_text = requests.get(url,headers=headers).text
#print(page_text)
tree = etree.HTML(page_text)
div_list = tree.xpath('//div[@class="col1 old-style-col1"]/div')
print(div_list)
for div in div_list:
    author = div.xpath('./div[1]/a[2]/h2/text() | ./div[1]/span[2]/h2/text()')[0]
    # 糗事百科中有作者和段子内容,作者分为实名用户和匿名用户,但通过对糗事百科的源码,当是匿名用户的时候,文本内容就取不到,所以返回None,但是爬取到的内容也就是None,不是想要的结果,解决:  ./div[1]/a[2]/h2/text()取实名用户,./div[1]/span[2]/h2/text()取匿名用户
    content = div.xpath('.//div[@class="content"]/span//text()')
    content = ''.join(content)
    print(author,content)

输出:

撞死一只羊
 


上周公司去日料店聚餐,没想到平时有女神光环的一位女生,一脱下鞋的那股酸臭味,把在场的人都纷纷「震撼」住了。臭就算了,居然还没穿袜子!可想而知那双脚的攻击性有多强!当时我的心情是已经不想干饭了,想赶紧跑。而女神自己也尴尬到跑去找卫生间洗脚。不然难以想象一顿有味道的午餐怎么吃得下去。过后我悄悄问女神,为啥那天没穿袜子,她说实在是找不到合适的袜子搭配那双鞋!



邱子是漂亮的
 


今天我两个同事吵架了,不管我怎么劝,他们就是不肯打架



骑着二哈啃黄瓜
 


闺蜜喝酒不爱去第二场,就是k t v,,,,好死不死,又被我拉去了,三杯酒下肚,就嗨起来了,比谁都会玩,中途她有电话,包厢太吵,她就出去接,一出门就被服务员告诫了:姑凉,我们这里不允许窜野台哦。。。

爬取糗事百科笑话的标题和内容

http://www.lovehhy.net/Joke/Detail

from lxml import etree
import requests
url = 'http://www.lovehhy.net/Joke/Detail/QSBK/'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
    'Cookie':'bdshare_firstime=1573442373487; ASP.NET_SessionId=0yoewt3nnhet3apass0u4hj5; ASPSESSIONIDQADBDDCA=AAKLABFACJHJNHHCMCKEJGJB; __51cke__=; Hm_lvt_03da7ad267ef3d61ce133d6c12f67140=1573442375,1573478536; ASPSESSIONIDSACCBCCA=BCOLDPEALOKMHFJJMHODNHGB; Hm_lpvt_lovehhy=1573479577; Hm_lvt_lovehhy=1573479577; Hm_lpvt_03da7ad267ef3d61ce133d6c12f67140=1573479707; __tins__2343955=%7B%22sid%22%3A%201573478536404%2C%20%22vd%22%3A%2011%2C%20%22expires%22%3A%201573481507039%7D; __51laig__=11'
}
joke_text = requests.get(url=url,headers=headers).text
#print(joke_text)
tree = etree.HTML(joke_text)
url_text = tree.xpath('//*[@class="post_recommend_new"]/h3/a/@href')
#url_text
for i in url_text:
    qiu_url =  i
    print(i)
    content_text = requests.get(url=qiu_url,headers=headers).text
    tree = etree.HTML(content_text)
    title = tree.xpath('//*[@id="read"]/h1/text()')[0]
    content = tree.xpath('//*[@id="fontzoom"]/text()')[0]
    print(title,content)

输出:

http://www.lovehhy.net/Yulu/View/170956

                图文语录 - 生活中难免有不如意的时候 
                  “   生活中难免有不如意的时候   路还很长 你不要绝望   打起精神来重新出发   温暖的事以后一定会发生的                                                      ” ?
http://www.lovehhy.net/Yulu/View/170955

                图文语录 - 但我希望对方可以肯定我 
                  “ 我喜欢能带给我正面影响的人,正面的影响不代表对方有多棒,但我希望对方可以肯定我,看得到我身上发光的地方,我也愿意回馈对方同等分量的重视。”

https://blog.csdn.net/weixin_42763696/article/details/108712503
https://www.cnblogs.com/tangjian219/p/11978047.html

相关文章

  • XPath 解析对象

    普通字符串数据需要将其初始化生成XPath解析对象才能利用XPath解析

  • 《七天爬虫进阶系列》 - 02 数据解析之 XPath

    数据解析是爬虫操作的第二步,本篇主要阐述采用XPath模块解析爬取到的数据。 XPath语法和lxml模块 什么是...

  • 数据解析-Xpath

    1. xpath安装及基本语法 1.xpath的解析原理实例化一个etree类型的对象,且将页面源码数据加载到该对...

  • Java EE -> Xml [QR]

    大纲: XML解析 引入 重点DOM解析SAX解析DOM解析 VS SAX解析 xPath技术 引入 xPath作...

  • Python爬虫实战-抓取Boss直聘招聘信息

    爬取过程: 1、获取数据:Requests 2、解析数据:xpath 3、保存数据:pandas 在boss中查询...

  • Python(七)

    数据解析 正则 bs4 xpath 数据解析原理概述: 解析的局部的文本内容都会在标签之间或者标签对应的属性中进行...

  • 蜻蜓点水XPath

    Scrapy推荐XPath解析数据,我们就把XPath干熟了,你会发现,真是好,越干越爽! 最简单的几个: 1 /...

  • Python爬虫小分队课程视频集

    课程视频 程工 Xpath语法解析 Json解析 mysql自动建表插入数据 函数和类封装调用 数据处理etl-e...

  • 解析库 -- lxml

    安装lxml库 (支持HTML和XML解析,支持XPath解析方式) Xpath 在 XPath 中,有七种类型的...

  • 使用Scrapy框架 爬取简书首页文章(XPath)

    1、简历Scrapy工程 2、建立Spider 3、解析Response(使用XPath) 第一页的数据解析比较简...

网友评论

      本文标题:数据解析-Xpath

      本文链接:https://www.haomeiwen.com/subject/gzqyeltx.html