爬虫之xpath表达式

说明

总结自己在爬虫过程中遇到的xpath表达式用法

在爬虫解析网页的时候,有多种方式可以可以提取网页元素。比如最基本的正则表达式、xpath、bs4、以及在scrapy中的css选择器。对于这些工具在爬虫的时候都遇到过,但是唯独喜欢用xpath,感觉提取很简介。同时也会掺杂一些正则表达式来做一些小的提取。

在记录xpath用法时,这里没有实际网页操作,仅当记住这种语法就是了。

操作语法

1、从根节点取元素,一般为<html>

/

2、选择所有的节点

//

这个表示选择所有的节点,例如 //div 表示选择网页中所有的div标签的内容。

3、添加元素的属性

@

例如:选取所有div下属性为class=nav的a标签下的href属性的值。

//div[@class="nav"]/a/@href

4、获取标签下的文本数据。

text()

例如:选取class="nav"的div下的ul下的li中所有的文本数据。

//div[@class="nav"]/ul/li/text()

5、选取某个大的标签下的所有文本数据,例如有个p标签,下面有span以及a标签,两个里面都有我们需要提取的文本,同时有可能在下一个p标签里面还有strong、h3等标签,此时我们需要使用string(.)

xpath('//div[@class="content"]//p').xpath("string(.)").extract()

高级语法

1、starts-with()

它是用来表示,某个属性以什么开头。

例如:我们在ul下有100个li标签,但是他们的id等于node1到node100,此时我们只需要这样写就可以提取。

xpath('//ul/li[starts-with(@id,"node")]/text()').extract()

2、contains()

它是用来指定某些元素包含了什么样的值,可以是属性,可以是文本。

例如:有个div标签下有class属性,它的值包含了,fh24 wh120 lx10等,此时你就可以下如下表达式来提取。

xpath('//div[contains(@class,"fh24")]/text()').extract()

同时你也可以用文本来作为提取标准,比如说,你想要提取下一页的链接。

xpath('//a[contains(text(),"下一页")]/@href').extract()

3、position()

这个是用来指定某个标签的位置。

例如:在ul标签下,有100li个标签,你想要提取第50个。

xpath('//ul/li[position()=50]/text()').extract()

4、last()

这个方法是用来指定,最后一个元素。

例如在class=nxt的div下面有5个a标签,我们需要最后一个,并且在下一页个数还会发生变化。此时就可以用last()。

xpath('//div[@class="nxt"]/a[last()]/@href').extract()

5、not()

这个方式是用来说明,某个标签不包含什么。

例如:在class=list的div元素中,其下面有20个a标签,其中这些a标签分为两类,一类有class="text"属性,一类没有。然而你想要提取没有属性的那一批。此时你可以这样写。

xpath('//div[@class="list"]/a[not(@class,"text")]/text()').extract()

xpath运算

同样的在xpath中,xpath也支持各种运算符。

最常见的以及最常用的主要包含

- 减

or 或者

and 和

> 大于

< 小于

= 等于

1、减法运算

比如我们需要获取倒数第二个标签。在class="list"的div下有20个a标签,你需要获取倒数第二个a标签的href

xpath('//div[@class="list"]/a[last()-1]/@href')

2、or运算,或运算

例如:在class="list"的div标签里面有100个a标签,其中有的a标签class="fh24",有的a标签class="wh20",有的a标签class="lx10",此时你只需要class="wh20"和class="lx10"的a标签,此时你可以这样做。

xpath('//div[@class="list"]/a[@class="wh20" or @class="lx10"]/text()').extract()

3、and运算,且运算,道理同上栗子就不举了。

4、>、<、=运算

例如:在id=title的div下的ul有100个li,你想要获取第23到98的li。你可以这样写。

xpath('//div[@id="title"]/ul/li[position()>=23 or position()<=98]/text()').extract()

 

<think>好的,我现在要比较Java和PythonXPath表达式的使用方式,特别是语法差异。首先,我需要回忆一下两种语言在解析XML/HTML时常用的库,以及它们如何实现XPath。 对于Python来说,常见的库是lxml,它基于libxml2,支持XPath 1.0。用户可能在Python中使用etree模块的xpath方法,如html.xpath('//div[@class="example"]')。另外,可能还有像XPath表达式中的函数使用,比如text()或者@属性。 Java方面,常用的库可能是JAXP(Java API for XML Processing),包括XPathFactory和XPathExpression。比如,使用DocumentBuilder解析文档,然后通过XPath的evaluate方法执行表达式。Java的XPath实现通常也遵循XPath 1.0,但可能有不同的API设计。 接下来,我需要考虑语法差异。比如,在Pythonlxml中,可能可以直接在XPath中使用某些扩展函数,或者处理命名空间的方式不同。而Java可能需要显式地处理命名空间,通过NamespaceContext来映射前缀和URI。 另外,表达式中的轴(axes)和节点测试是否有差异?例如,在Python中是否支持某些简写,或者Java是否要求更严格的语法。例如,在Python中可以直接用//div[@class],而Java是否需要更明确的轴步骤? 还有,结果返回的处理。Pythonlxml返回的可能是元素列表,直接获取属性或文本,而Java可能需要通过NodeList遍历,再提取内容。例如,在Python中html.xpath('//a/text()')会得到文本列表,而Java可能需要调用evaluate表达式并转换为节点,再获取节点值。 另外,错误处理可能有差异。比如,Python中如果表达式写错,可能会抛出异常,而Java的XPath可能返回空节点或异常,需要不同的处理方式。 需要确认两种语言在XPath表达式语法本身是否一致。比如,是否都支持相同的运算符、函数,或者是否有特定实现的不同。例如,contains()函数的使用是否有差异,或者字符串处理的函数是否支持相同参数。 然后,参考用户提供的引用,其中提到了Python中使用lxml的案例,如html.xpath('//a/img/@src'),这在Java中如何实现?可能需要使用类似的表达式,但API调用方式不同。 还要注意,Java中XPath的评估可能需要编译表达式,比如XPathExpression对象,而Pythonlxml可能直接执行字符串表达式。性能方面是否有差异? 最后,总结主要差异点:API设计、命名空间处理、结果处理方式、扩展函数支持、错误处理等。需要具体举例说明,比如同样的XPath表达式在两种语言中的写法是否相同,调用方式的不同,以及处理结果的方式。</think>### Java与PythonXPath表达式使用方式对比 #### 一、语法核心差异 1. **表达式语法一致性** Java和PythonXPath语法在核心部分完全兼容,均遵循XPath 1.0标准[^1]。例如,选择`class="title"`的`<span>`元素均可用: ```xpath //span[@class='title'] ``` 但在扩展函数支持上,Python的`lxml`可能支持部分非标准语法(如`starts-with`的简化写法),而Java更严格遵循标准。 2. **命名空间处理** - **Python**:通过`nsmap`参数显式声明命名空间: ```python namespaces = {'ns': 'http://example.com'} html.xpath('//ns:div', namespaces=namespaces) ``` - **Java**:需使用`NamespaceContext`绑定前缀与URI: ```java XPathFactory xpathFactory = XPathFactory.newInstance(); XPath xpath = xpathFactory.newXPath(); xpath.setNamespaceContext(new NamespaceContext() { public String getNamespaceURI(String prefix) { return "http://example.com"; } }); NodeList nodes = (NodeList) xpath.evaluate("//ns:div", document, XPathConstants.NODESET); ``` #### 二、API使用方式对比 1. **Pythonlxml库)** - **直接执行表达式**:通过`etree`对象的`xpath()`方法直接返回结果列表: ```python titles = html.xpath('//span[@class="title"]/text()') # 提取文本 image_urls = html.xpath('//a/img/@src') # 提取属性[^2] ``` - **结果类型**:自动转换为字符串列表或元素列表。 2. **Java(JAXP API)** - **编译与执行分离**:需先编译XPath表达式: ```java XPathExpression expr = xpath.compile("//span[@class='title']"); NodeList nodes = (NodeList) expr.evaluate(document, XPathConstants.NODESET); ``` - **手动提取内容**:遍历`NodeList`并提取属性或文本: ```java for (int i=0; i<nodes.getLength(); i++) { Element span = (Element) nodes.item(i); String title = span.getTextContent(); } ``` #### 三、扩展功能差异 1. **Python的灵活性** - 支持XPath表达式内联函数,如`contains()`: ```xpath //div[contains(@class, "result")] ``` - 支持直接提取多个属性或层级数据(如`/text()`或`/@src`)[^3]。 2. **Java的限制** - 需依赖第三方库(如Saxon-HE)才能支持XPath 2.0+的高级功能。 - 默认仅支持XPath 1.0,复杂操作需结合DOM API手动处理。 #### 四、典型代码示例对比 | 功能 | Python (lxml) | Java (JAXP) | |--------------------|----------------------------------------|----------------------------------------| | 提取元素文本 | `html.xpath('//span/text()')` | `evaluate("//span", document, NODESET)` + 遍历提取`getTextContent()` | | 提取属性值 | `html.xpath('//img/@src')` | `evaluate("//img/@src", document, STRING)` | | 条件过滤 | `//div[@class="main"][position()=1]` | 语法相同,但结果需手动处理索引 | #### 五、性能与适用场景 - **Python**:适合快速开发,表达式简洁,适合HTML解析(如结合`requests`爬虫)[^2]。 - **Java**:适合企业级应用,需高稳定性,但代码量较大。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值