您的位置:首页 > 编程语言 > Python开发

Python爬虫——4-2.数据筛选之XPath

2018-01-12 21:52 190 查看

爬虫数据筛选——XPath

        在使用爬虫爬取的数据可以分为两种,非结构化数据:数据的内容没有固定的格式和规范,如用户名、邮箱、账号、电话号码、地址、电影名称、评分、评论、商品名称等等,对此类数据的筛选我们一般使用正则表达式,效率较高且非常精准,而对于一些有特定规范的数据如HTML网页文档、XML网页文档、JSON等等,由于数据本身存在一定的规律性,可以通过针对这些规律的分析工具进行数据的提取:**正则表达式、Xpath、BeautifulSoup4、select、css等等,本篇我们主要学习XPath,做个笔记,方便以后学习吧~

Xpath原本是在可扩展标记语言XML中进行数据查询的一种描述语言,可以很方便的在XML文档中查询到具体的数据;后续再发展过程中,对于标记语言都有非常友好的支持,如超文本标记语言HTML。

一、认识Xpath

1.Xpath应用环境的搭建——lxml的安装

      正如在python中有一个内置的re模块用来支持正则表达式语法一样,python中有一个第三方的lxml模块,可以方便的支持Xpath的各种操作,可以友好的解析Xpath语法,使其用于在程序中进行结构化数据筛选。

安装命令如下:

pip install lxml

python2 -m pip install lxml

pip2 install lxml

2.在操作Xpath之前,首先需要了解一些基础的技术术语

* 根标签:在标记语言中,处在最外层的一个标签就是根标签,根标签有且仅有一个,在上述代码中\<html\>就是跟标签

* 父标签:和子标签对应,内部包含了其他元素数据,该标签就是内部标签的父标签,如\<html\>是\<head\>的父标签,\<head\>又是\<title\>的父标签,某些说法中,父标签的父标签..被称为上级标签或则先代标签或者先辈标签

* 子标签:和父标签对应,被包含的元素,就是外部元素的子标签,如\<head\>是\<html\>的子标签,\<title\>标签是\<head\>的子标签,\<tr\>是\<table\>的子标签;同样的子标签的子标签,也被称为后代标签

* 兄弟标签:两个或者多个处在相同级别的标签,有相同的父标签,如\<h1\>和\<table\>是兄弟标签,\<head\>和\<body\>是兄弟标签,\<table\>中的两个\<tr\>是兄弟标签等等
* Xpath描述语言的常见语法

和正则表达式相比较,Xpath使用最简单的语法操作完成数据的查询匹配操作
表达式 |描述

-|-

nodename| 选取此节点的所有子节点。

/| 从根节点选取。

//| 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。

.| 选取当前节点。

..| 选取当前节点的父节点。

@| 选取属性。

*| 匹配任何元素节点。

@*| 匹配任何属性节点。

node()| 匹配任何类型的节点。

通过如下的方式直接操作上面的文档

路径表达式 | 结果

-|-

html| 选取 html 元素的所有子节点。

/html| 选取根元素 html。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!

table/tr/td| 选取属于 table 的子元素的所有 td 元素。

//div \| //table|选取所有的div或者table节点

//table|选取所有 table 子元素,而不管它们在文档中的位置。

html//div|选择属于html元素的后代的所有div元素,而不管它们位于 html之下的什么位置。

//@href |选取名为href 的所有属性。

标签条件筛选查询匹配

路径表达式 | 结果

-|-

//table/tr[1] | 选取属于table子元素的第一个 tr 元素。

//table/tr[last()] | 选取属于 table 子元素的最后一个 tr 元素。

//table/tr[last()-1] | 选取属于 table 子元素的倒数第二个 tr 元素。

//table/tr[position()<3] | 选取最前面的两个属于 table 元素的子元素的tr元素。

//td[@width] | 选取所有拥有名为 width 的属性的 td 元素。

//td[@width='100'] | 选取所有 td 元素,且这些元素拥有属性width并且值为100。

//tr//td[span>10000] | 选取tr元素的所有td子元素,并且其中的span 元素的值须大于10000。

同样,Xpath支持数据运算操作

运算符| 描述|
实例| 返回值

-|-|-|-

+ |加法 |6 + 4|
10

- |减法 6 - 4|
2

* |乘法 6 * 4|
24

div |除法
8 div 4| 2

= |等于|
price=9.80 |如果 price 是 9.80,则返回 true。如果 price 是 9.90,则返回 false。

!=|不等于|price!=9.80 |如果 price 是 9.90,则返回 true。如果 price 是9.80,则返回 false。

< |小于|
price<9.80 |如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。

<= |小于或等于
|price<=9.80 |如果 price 是 9.00,则返回 true。如果 price 是 9.90,则返回 false。

> |大于|
price>9.80 |如果 price 是 9.90,则返回 true。如果 price 是 9.80,则返回 false。

>= |大于或等于|
price>=9.80 |如果 price 是 9.90,则返回 true。如果 price 是 9.70,则返回 false。

or |或|
price=9.80 or price=9.70 |如果 price 是 9.80,则返回 true。如果 price 是 9.50,则返回 false。

and |与
|price>9.00 and price<9.90 |如果 price 是 9.80,则返回 true。如果 price 是 8.50,则返回 false。

mod |计算除法的余数
|5 mod 2 |1

xpath在浏览器中进行测试时,可以给谷歌浏览器安装一个插件Xpath Helper插件;就可以直接在浏览器中通过xpath语法来完成对数据的匹配测试

测试通过的xpath语法,就可以直接在程序中使用了!

二、python操作Xpath

python第三方模块lxml可以对Xpath有友好的支持,lxml是C实现的一种高性能python用于HTML/XML的解析模块,可以通过Xpath语法在html文档数据中进行指定表达式数据的索引查询

* 简单etree操作

```

# -*- coding:utf-8 -*-

from lxml import etree

# 模拟得到爬虫数据

content = """

    <html>

        <head>

            <title>大牧</title>

        </head>

        <body>

            <h1>个人简介</h1>

            <div>

                <p>姓名:某某某</p>

                <p>住址:中国 乡下</p>

                <p>座右铭:岂能尽如人意,但求无愧于心</p>

            </div>

        </body>

    </html>

"""

# 转换成html数据

# html = etree.parse("index.html")# 从文件中直接加载html数据

html = etree.HTML(content)# 通过etree.HTML()函数将字符串转换成HTML文档对象

print dir(html)# 查看文档对象的所有函数

print html.getchildren()# 查看文档对象根节点的所有子节点

# 转换成字符数据

str_html = etree.tostring(html)# 将HTML文档对象转换成字符串

print type(str_html)# 查看输出类型

print str_html# 查看输出数据

* xpath操作

```

# -*- coding:utf-8 -*-

from lxml import etree

# 模拟得到爬虫数据

content = u"""

    <html>

        <head>

            <title>大牧</title>

        </head>

        <body>

            <h1 name="title">个人简介</h1>

            <div name="desc">

                <p name="name">姓名:<span>某某某</span></p>

                <p name="addr">住址:中国 乡下</p>

                <p name="info">座右铭:岂能尽如人意,但求无愧于心</p>

            </div>

        </body>

    </html>

"""

# 将爬取到的数据转换成HTML文档

html = etree.HTML(content)

# 查询所有的p标签

p_x = html.xpath("//p")

print(p_x)

# 查询所有Name属性的值

v_attr_name= html.xpath("//@name")

print(v_attr_name)

# 查询所有包含name属性的标签

e_attr_name = html.xpath("//*[@name]")

print(e_attr_name)

# 查询所有包含name属性,并且name属性值为desc的标签

e_v_attr_name = html.xpath("//*[@name='desc']")

print(e_v_attr_name)

# 查询所有p标签的文本内容,不包含子标签

p_t = html.xpath("//p")

for p in p_t:

    print (p.text)

# 查询多个p标签下的所有文本内容,包含子标签中的文本内容

p_m_t = html.xpath("//p")

for p2 in p_m_t:

    print(p2.xpath("string(.)"))

```
案例操作:爬虫智联招聘中前10页的某个工作岗位名称、薪水、公司信息



# coding:utf-8
'''
使用xpath爬取智联招聘职位信息
'''
import requests
from lxml import etree

# 访问路由
url='http://sou.zhaopin.com/jobs/searchresult.ashx?jl=%E5%8C%97%E4%BA%AC%2B%E4%B8%8A%E6%B5%B7%2B%E5%B9%BF%E5%B7%9E%2B%E6%B7%B1%E5%9C%B3&kw=python%E5%BC%80%E5%8F%91%E5%B7%A5%E7%A8%8B%E5%B8%88&p=1&isadv=0'
# 设置访问头
headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36'
}
# 发送请求
response=requests.get(url,headers=headers)

# 根据网页数据,转换为html
html=etree.HTML(response.text)

# 使用xpath语法进行匹配
# 获取职位名称
job_names=html.xpath("//table[@class='newlist']/tr[1]/td[@class='zwmc']/div")
#job_names=html.xpath("//div[@id='newlist_list_content_table']/table[@class='newlist']/tr[1]/td[@class='zwmc']/div/a")
# 定义职位名称列表
name_list=[]
for job_name in job_names:
job_name2=job_name.xpath('string(.)').strip()
name_list.append(job_name2)

# 获取职位月薪
month_nums=html.xpath("//table[@class='newlist']/tr[1]/td[@class='zwyx']")
#定义保存月薪的列表
num_list=[]
for num in month_nums:
num2=num.xpath('string(.)').strip()
num_list.append(num2)

# 获取公司名称
company_names=html.xpath("//table[@class='newlist']/tr[1]/td[@class='gsmc']")
#定义保存月薪的列表
company_list=[]
for company_name in company_names:
company_name2=company_name.xpath('string(.)').strip()
company_list.append(company_name2)

max_list=[]
max_list.append(name_list)
max_list.append(num_list)
max_list.append(company_list)

f = open('zl.txt', 'w')
i=0
for i in range(0,len(company_list)):
info= max_list[0][i]+'|'+max_list[1][i]+'|'+max_list[2][i]+"\r\n"
print info
f.write(info.encode('utf-8'))
f.close()

# 打开zl.txt文件,保存内容格式如下
'''
python开发工程师|10001-15000|乐飞天下信息技术(北京)有限公司Python开发工程师|15001-20000|乐飞天下信息技术(北京)有限公司python开发工程师|6001-8000|北京红枣科技有限公司......
'''


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: