【scrapy】3.XPath解析

目录

一、XPath介绍

1.基本介绍

2.HTML树状结构图

3.节点之间的关系

(1)Xpath中的绝对路径与相对路径

二、XPath的语法介绍

1.元素属性定位

1.1 根据属性名定位元素:

1.2 根据属性名和属性值定位元素:

1.3 根据部分属性值定位元素:

1.4 根据多个属性进行定位:

2.层级属性结合定位

2.1定位父元素下的子元素:

2.2 定位特定属性的父元素下的子元素:

2.3定位特定属性的父元素下的特定属性的子元素:

3.使用谓语定位

3.1定位符合特定索引的元素:

3.1定位满足特定属性条件的元素:

3.3结合多个条件定位元素:

3.4通过文本内容定位元素:

4.使用逻辑运算符定位

4.1 使用 and 运算符:

4.2 使用 or 运算符:

4.3 使用 not 运算符:

5.使用文本定位

5.1定位文本内容相等的元素:

5.2定位包含指定文本内容的元素:

5.3根据包含特定关键词的文本内容定位元素:

6.使用部分函数定位

三、XPath语法验证

四、lxml的基本使用


一、XPath介绍

1.基本介绍

XPath(XML Path Language)是一种XML的查询语言,他能在XML树状结构中寻找节点。XPath 用于在 XML 文档中通过元素和属性进行导航

xml是一种标记语法的文本格式,xpath可以方便的定位xml中的元素和其中的属性值。lxml是python中的一个第三方模块,它包含了将html文本转成xml对象,和对对象执行xpath的功能

2.HTML树状结构图

3.节点之间的关系

Xpath 中的绝对路径从 HTML 根节点开始算,相对路径从任意节点开始。通过开发者工具,我们可以拷贝到 Xpath 的绝对路径和相对路径代码:

绝对路径

#从根节点/html开始往下,一层层的表示 出来直到需要的节点为止。

/html/body/div[1]/div[2]/div[6]/div/div/div[2]/div/div[1]/div/div[1]/div/div/ul/li[1]/a/span[1]

相对路径

#以“//”开头。可以从任意节点开始,一般选取一个可以唯一定位到的元素开始写

//*[@id="title-content"]/span[1]

但是由于拷贝出来的代码缺乏灵活性,也不全然准确。大部分情况下,都需要自己定义 Xpath 语句。

二、XPath的语法介绍

表达式说明举例
/从根节点开始选取/html/div/span
//从任意节点开始选取//*[@id="kw"]
.选取当前节点
..选取当前节点的父节点//input/..       #会选取 input 的父节点
@选取属性或者根据属性选取

//input[@data]     #选取具备 data 属性的 input 元素

//@data           #选取所有 data 属性

*通配符,表示任意节点或任意属性

路径表达式描述
bookstore选取bookstore元素的所有子节点
/bookstore选取根元素bookstore,假如路径起始于“/”,则此路径始终代表到元素的绝对路径
//bookstore选取属于bookstore的子元素的所有book元素
bookstore/book选取所有book子元素,而不管它们在文档中的位置
//book选择属于bookstore元素的后代的任意位置的所有book元素
//@lang选取名为lang的所有属性

1.元素属性定位

1.1 属性名定位元素:

        定位具有特定属性名的元素://*[@attribute_name]

        示例://*[@class] 会匹配所有具有 "class" 属性的元素。

1.2 属性名和属性值定位元素:

        定位具有特定属性名和属性值的元素://*[@attribute_name='value']

        示例://*[@id='myElement'] 会匹配 id 属性值为 "myElement" 的元素。

1.3 部分属性值定位元素:

        定位具有属性值包含特定文本的元素://*[contains(@attribute_name,'value')]

        示例://*[contains(@class,'active')] 会匹配 class 属性值包含 "active" 的元素。

1.4 多个属性进行定位:

        定位具有多个属性及其对应值的元素://*[@attribute_name_1='value_1' and   @attribute_name_2='value_2']

        示例://*[@class='active' and @data-type='button'] 会匹配同时具有 class 属性值为         "active" 和 data-type 属性值为 "button" 的元素

2.层级属性结合定位

2.1定位父元素下的子元素:

   //父元素名/子元素名:通过指定父元素和子元素的标签名来定位元素。

2.2 定位特定属性的父元素下的子元素:

  //父元素名[@属性名='属性值']/子元素名   

通过指定父元素的属性和属性值,再结合子元素的标签名来定位元素。

示例://div[@class='container']/p   

会匹配 class 属性为 "container" 的 <div> 元素下的所有 <p> 元素。

2.3定位特定属性的父元素下的特定属性的子元素:

   //父元素名[@属性名1='属性值1']/子元素名[@属性名2='属性值2']:通过指定父元素和子元素的属性条件来定位元素。

示例://ul[@id='menu']/li[@class='active']

会匹配 id 属性为 "menu" 的 <ul> 元素下,class 属性为 "active" 的所有 <li> 元素。

3.使用谓语定位

谓语用来查找某个特定的节点或者包含某个指定的值的节点,谓语被嵌在方括号中。

3.1定位符合特定索引的元素:

   //tagname[position()]:通过位置索引来定位元素。索引从 1 开始。

   示例://ul/li[position() = 3] 可以匹配位于 <ul> 下的第三个 <li> 元素。

3.1定位满足特定属性条件的元素:

    //tagname[@attribute='value']:通过属性条件来定位元素。

   示例://input[@type='text'] 可以匹配所有 type 属性值为 "text" 的 <input> 元素。

3.3结合多个条件定位元素:

    //tagname[@attribute1='value1' and @attribute2='value2']:使用逻辑运算符 and 结合多个属性条件来定位元素。

    示例://a[@class='active' and @href='/home'] 可以匹配同时满足 class 属性值为 "active" 和 href 属性值为 "/home" 的 <a> 元素。

3.4通过文本内容定位元素:

    //tagname[text()='value']:通过文本内容来定位元素。

    示例://h1[text()='Welcome']

可以匹配文本内容为 "Welcome" 的 <h1> 元素。

4.使用逻辑运算符定位

使用逻辑运算符定位是XPath中一种灵活的定位技术,允许您结合多个条件来定位元素。XPath支持以下三种逻辑运算符:and、or、not。以下是使用逻辑运算符定位元素的示例:

4.1 使用 and 运算符:

//tagname[@attribute1='value1' and @attribute2='value2']:通过结合多个属性条件,使用 and 运算符定位元素。

示例://input[@type='text' and @name='username'] 可以匹配type属性为"text"且name属性为"username"的input元素。

4.2 使用 or 运算符:

//tagname[@attribute='value1' or @attribute='value2']:通过结合多个属性条件,使用 or 运算符定位元素。

示例://a[@class='active' or @class='highlight'] 可以匹配class属性为"active"或"class"属性为"highlight"的a元素。

4.3 使用 not 运算符:

//tagname[not(@attribute='value')]:使用 not 运算符否定一个属性条件,定位不满足该条件的元素。

示例://div[not(@class='header')] 可以匹配class属性不为"header"的div元素

5.使用文本定位

5.1定位文本内容相等的元素:

//tagname[text()='value']:匹配文本内容与指定值相等的元素。

示例://a[text()='Login'] 可以匹配文本为"Login"的所有 <a> 元素。

5.2定位包含指定文本内容的元素:

//tagname[contains(text(),'value')]:匹配包含指定值的文本内容的元素。

示例://p[contains(text(),'Lorem ipsum')] 可以匹配包含"Lorem ipsum"文本的所有 <p> 元素。

5.3根据包含特定关键词的文本内容定位元素:

//tagname[contains(text(),'keyword')]:匹配文本内容中包含特定关键词的元素。

示例://h2[contains(text(),'Contact')] 可以匹配文本内容中包含"Contact"关键词的 <h2> 元素

6.使用部分函数定位

函数

说明举例
contains(a,b)选取属性或者文本包含某些字符//div[contains(@id, 'data')] 选取 id 属性包含 data 的 div 元素
start-with(a,b)选取属性或者文本以某些字符开头//div[starts-with(@id, 'data')] 选取 id 属性以 data 开头的 div 元素
end-with(a,b) 选取属性或者文本以某些字符结尾//div[ends-with(@id, 'require')] 选取 id 属性以 require 结尾的 div 元素


                        

三、XPath语法验证

(1)在开发者工具的 Elements 中按Ctrl + F,在搜索框中输入 Xpath

(2)打开开发者工具并切换到Console(控制器),在Console中输入$x('具体的XPath')并回车执行

四、lxml的基本使用

lxml是一个HTML/XML的解析器,主要的功能是解析和提取HTML/XML数据

lxml和正则一样,也是用C语言实现的,可以利用之前学习的XPath语法,来快速的定位元素及节点信息。

# 导入模块
from lxml import etree
# html源代码
web_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转成xml文件
element = etree.HTML(web_data)
# print(element)
# 获取li标签下面的a标签的href
links = element.xpath('//ul/li/a/@href')
print(links)
# 获取li标签下面的a标签的文本数据
result = element.xpath('//ul/li/a/text()')
print(result)

注:

  • '//ul/li/a/@href':选择并返回<a>标签的href属性值,返回一个字符串列表。
  • '//ul/li/a[href]':选择并返回包含href属性的<a>标签元素,返回一个元素列表(Element对象)。
  • '//ul/li/a/text()':获取<a>标签的文本内容。

参考:数据解析之Xpath解析(超详细定位)-CSDN博客

JsoupXpath 是一款纯Java开发的使用xpath解析html的解析器,xpath语法分析与执行完全独立,html的DOM树生成借助Jsoup,故命名为JsoupXpath.为了在java里也享受xpath的强大与方便但又苦于找不到一款足够强大的xpath解析器,故开发了JsoupXpath。JsoupXpath的实现逻辑清晰,扩展方便,支持几乎全部常用的xpath语法.http://www.cnblogs.com/ 为例 "//a/@href"; "//div[@id='paging_block']/div/a[text()='Next >']/@href"; "//div[@id='paging_block']/div/a[text()*='Next']/@href"; "//h1/text()"; "//h1/allText()"; "//h1//text()"; "//div/a"; "//div[@id='post_list']/div[position()1000]/div/h3/allText()"; //轴支持 "//div[@id='post_list']/div[self::div/div/div/span[@class='article_view']/a/num()>1000]/div/h3/allText()"; "//div[@id='post_list']/div[2]/div/p/preceding-sibling::h3/allText()"; "//div[@id='post_list']/div[2]/div/p/preceding-sibling::h3/allText()|//div[@id='post_list']/div[1]/div/h3/allText()"; 在这里暂不列出框架间的对比了,但我相信,你们用了会发现JsoupXpath就是目前市面上最强大的的Xpath解析器。 快速开始 如果不方便使用maven,可以直接使用lib下的依赖包跑起来试试,如方便可直接使用如下dependency(已经上传至中央maven库,最新版本0.1.1):    cn.wanghaomiao    JsoupXpath    0.1.1 依赖配置好后,就可以使用如下例子进行体验了!String xpath="//div[@id='post_list']/div[./div/div/span[@class='article_view']/a/num()>1000]/div/h3/allText()";String doc = "..."; JXDocument jxDocument = new JXDocument(doc); List<Object> rs = jxDocument.sel(xpath); for (Object o:rs){     if (o instanceof Element){             int index = ((Element) o).siblingIndex();             System.out.println(index);     }     System.out.println(o.toString()); } 其他可以参考 cn.wanghaomiao.example包下的例子 语法 支持标准xpath语法(支持谓语嵌套),支持全部常用函数,支持全部常用轴,去掉了一些标准里面华而不实的函数和轴,下面会具体介绍。语法可以参考http://www.w3school.com.cn/xpath/index.asp 关于使用Xpath的一些注意事项 非常不建议直接粘贴Firefox或chrome里生成的Xpa
根据你提供的代码和报错信息,我猜测可能是你的项目结构和文件命名有问题。建议你按照 Scrapy 官方文档的要求进行项目创建和文件命名,比如: 1. 项目名应该是一个有效的 Python 标识符,建议使用小写字母和下划线,比如 `myproject`。 2. Spider 类的文件名应该与 Spider 类的 `name` 属性相同,比如 `ygspider.py`。 3. Items 类的文件名应该是 `items.py`。 具体的代码实现如下: `myproject/spiders/ygspider.py` ```python import scrapy from myproject.items import YgItem class YgSpider(scrapy.Spider): name = "ygspider" allowed_domains = ["sun0769.com"] start_urls = ["https://wz.sun0769.com/political/index/politicsNewest?id=1&page=1"] def parse(self, response): lilist = response.xpath('//ul[@class="title-state-ul"]/li') for li in lilist: item = YgItem() item['id'] = li.xpath('./span[1]/text()').extract_first() item['status'] = li.xpath('./span[2]/text()').extract_first() item['title'] = li.xpath('./span[3]/a/text()').extract_first() infohref = 'https://wz.sun0769.com' + li.xpath('./span[3]/a/@href').extract_first() item['retime'] = li.xpath('./span[4]/text()').extract_first() item['asktime'] = li.xpath('./span[5]/text()').extract_first() # 解析详情页 yield scrapy.Request(url=infohref, callback=self.parseinfo, meta={'item': item}) # 翻页 next_page = response.xpath('//[@class="arrow-page prov_rota"]/@href').extract_first() if next_page: next_page = 'https://wz.sun0769.com' + next_page yield scrapy.Request(url=next_page, callback=self.parse) def parseinfo(self, response): item = response.meta['item'] yield item ``` `myproject/items.py` ```python import scrapy class YgItem(scrapy.Item): id = scrapy.Field() status = scrapy.Field() title = scrapy.Field() retime = scrapy.Field() asktime = scrapy.Field() content = scrapy.Field() ``` 建议你按照上述方式进行代码重构,然后再运行一下看看是否能够正常抓取数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值