爬虫小菜:你知道xpath中text()和string(.)的区别吗?

我们在进行爬虫时候,经常会遇到如下这样的页面:

<span>
    <div>
        <em>你好</em>,北京
    </div>
</span>

在日常抓取的时候,遇到更多的情况是抓取<em>中的你好,这时使用xpath("//div/em/text()")就可以提取到。

现在我们考虑下面两种抓取需求:

需求1:我们想要提取“,北京”的时候,这个时候该用text(),还是string(.)?

需求2:提取 “你好,北京”呢?

我们先使用lxml库对页面进行一下初始化(如果你用的是scrapy的xpath选择器,也可以按照以下步骤运行):

from lxml import etree
with open('foo.html', 'r') as f:
    content = f.read().encode('utf8')
page = etree.HTML(content)

这里我们先看一下需求1的解法,也就是提取“,北京”:

re = page.xpath("//div/text()")

这里re得到的是一个数组:

这是因为在页面中标签<div>和<em>之间是有换行符号的,因此使用"//div/text()"后会忽略掉<em>你好</em>,而剩下"\n",“,北京\n”两个元素。

我们取re的第二个元素,然后去掉结尾的换行符"\n"(如果你使用的是scrapy的xpath,这里re得到的可能不是一个数组):

re = re[1].strip()

这个时候得到的re就是我们需要的",北京"了。

现在看一下第二个需求:提取"你好,北京":

这里就要求<em>里面的文本也要提取出来了,这时候我们使用string:

re = page.xpath("//div")[0].xpath("string(.)")

这时来看下re的值(同样如果你使用的是scrapy的选择器,scrapy_selector.xpath("//div")返回的结果可能不是一个数组,不过你只要取到结果然后再使用.xpath("string(.)")即可。):

得到的一整串文本" \n     你好,北京\n  "。

看来使用"string(.)"后,xpath会把<em>里的内容也直接提取出来,而不像上面中"text()"那样把<em>都去掉后,再分割成一个数组。这里注意使用string()时候要把string(.)放在一个xpath中,而不是写成"//div/string(.)"这样,否则会抓取不到。

然后,同样的再去除一下两边多余的空格和换行符

re = re.strip()

这个时候re得到就是”你好,北京“啦。

 

总结:

通过上述的实验,我们发现xpath里面text()只会取当层节点的文本并按照当层的tag进行分割,组成列表。而string(.)会把当层节点以及当层节点以下的所有文本都提取出来,放在一个字符串变量中。

 

 

 

实例代码:

test.py:

# coding=utf-8
from lxml import etree
import sys
reload(sys)
sys.setdefaultencoding('utf-8')


class Test(object):
    def __init__(self):
        with open('foo.html', 'r') as f:
            content = f.read().encode('utf8')
        self.page = etree.HTML(content)
        print self.page

    def xpath_text(self):
        re = self.page.xpath("//div/text()")
        print re
        re = re[1].strip()
        print re
        return re

    def xpath_string(self):
        re = self.page.xpath("//div")[0].xpath("string(.)")
        print re
        # 替换换行符等
        re = re.strip(re)
        print re
        return re

if __name__ == "__main__":
    t = Test()
    assert t.xpath_text() == u",北京"
    assert t.xpath_string() == u"你好,北京"

foo.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Example</title>
</head>
<body>
<span>
    <div>
        <em>你好</em>,北京
    </div>
</span>
</body>
</html>

 

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值