爬虫-xpath解析工具

XPath即为XML路径语言(XML Path Language);
在XML文档中查找信息的语言,同样适用于HTML文档的检索;
lxml库的使用

概念

在XML文档中查找信息的语言,同样适用于HTML文档的检索

xpath辅助工具

  1. Chrome安装插件方式

    1
    2
    3
    1、打开浏览器 - 设置 - 更多工具 - 扩展程序 
    2、右上角 :开发者模式
    3、从网上下载的插件 拖拽到 浏览器页面
  2. 网页解析相关插件

    1
    2
    3
    1、Chrome浏览器 :XPath Helper
    2、Firefox浏览器:XPath Checker
    3、XPath表达式编辑工具 :XML Quire
  3. 打开和关闭xpath辅助工具
    打开/关闭 :

    1
    ctrl + shift + x

xpath匹配规则

演示文档

匹配演示

  1. 查找bookstore下所有节点

    1
    /bookstore
  2. 查找所有的book节点

    1
    //book
  3. 查找所有book节点下的title节点

    1
    //book/title
  4. 查找//book/title节点中lang属性为 “en” 的节点

    1
    //book/title[@lang="en"]
  5. 获取bookstore节点下的第2个book节点下的title节点的文本内容

    1
    /bookstore/book[2]/title/text()

选取节点

1
2
//  :从整个HTML文档中查找节点
//price //book//price
1
2
3
@   :选取某个节点的属性
1、 //title[@lang="en"]
2、 //title/@lang
1
2
3
4
5
6
7
8
9
10
11
12
./  :选取已经存在的条件之上追加条件
aList = parseHtml.xpath('//div[@class="pl2"]')
for element in aList:
nameList = element.xpath('./a/text()')
if len(nameList) > 0:
name = nameList[0]
name = name.replace(" ", "")
name = name.replace("\n", "")
name = name.replace("\r", "")
name = name.replace("/", " / ")
else:
name = ""

匹配多路径

  1. 符号 :xpath表达式 | xpath表达式
  2. 获取所有book节点下的 title节点 和 price节点
    //book/title | //book/price

函数

  1. contains() :匹配一个属性值中包含某些字符串的节点
  2. text():将节点提取出字符串
1
//title[contains(@lang,"ch")]/text()

lxml库及xpath使用

HTML/XML解析库

安装

1
2
cmd -> python -m pip install lxml
Anaconda Prompt -> conda install lxml

使用流程(xpath返回的一定是1个列表)

  1. 导入模块

    1
    from lxml import etree
  2. 创建解析对象 :

    1
    parseHtml = etree.HTML(html)
  3. 调用xpath

    1
    rList = parseHtml.xpath('xpath表达式')

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
from lxml import etree

html = """
<div class="wrapper">
<i class="iconfont icon-back" id="back"></i>
<a href="/" id="channel">新浪社会</a>
<ul id="nav">
<li><a href="http://domestic.firefox.sina.com/" title="国内">国内</a></li>
<li><a href="http://world.firefox.sina.com/" title="国际">国际</a></li>
<li><a href="http://mil.firefox.sina.com/" title="军事">军事</a></li>
<li><a href="http://photo.firefox.sina.com/" title="图片">图片</a></li>
<li><a href="http://society.firefox.sina.com/" title="社会">社会</a></li>
<li><a href="http://ent.firefox.sina.com/" title="娱乐">娱乐</a></li>
<li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li>
<li><a href="http://sports.firefox.sina.com/" title="体育">体育</a></li>
<li><a href="http://finance.firefox.sina.com/" title="财经">财经</a></li>
<li><a href="http://auto.firefox.sina.com/" title="汽车">汽车</a></li>
</ul>
<i class="iconfont icon-liebiao" id="menu"></i>
</div>"""
# 创建解析对象
parseHtml = etree.HTML(html)
# 调xpath工具,得到列表
rList = parseHtml.xpath('//li/a/@href')
#print(rList)

# 获取 /
#r1=parseHtml.xpath('//a[@id="channel"]/@href')
r1=parseHtml.xpath\
('//div[@class="wrapper"]/a[@id="channel"]/@href')
#print(r1)

# 获取文本 :新浪社会、国际、国内
r2 = parseHtml.xpath('//a/text()')
#print(r2)

# 获取文本 :国际、国内、军事 ...
r3 = parseHtml.xpath('//ul[@id="nav"]//a')
# r3:['<element>','<element>']
for r in r3:
# text属性获取节点对象文本内容
print(r.text)

练习: xpath匹配猫眼电影

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
import requests
from lxml import etree

class MaoyanSpider:
def __init__(self):
self.headers = {"User-Agent":"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"}
self.baseurl = "http://maoyan.com/board/4?offset="
self.offset = 0
# 使用私密代理
self.proxies = {"http":"http://309435365:szayclhp@116.255.162.107:16816"}

# 获取页面
def getPage(self,url):
res = requests.get(url,
headers=self.headers)
res.encoding = "utf-8"
html = res.text
self.parsePage(html)

# 解析页面
def parsePage(self,html):
# 创建解析对象
parseHtml = etree.HTML(html)
# 调用xpath
nameList = parseHtml.xpath('//div[@class="movie-item-info"]/p[1]/a/text()')
starList = parseHtml.xpath('//div[@class="movie-item-info"]/p[2]/text()')
timeList = parseHtml.xpath('//div[@class="movie-item-info"]/p[3]/text()')

for name,star,time in zip(nameList,starList,timeList):
print(name.strip(),star.strip(),time.strip())

# L1 = [1,2,3]
# L2 = ['A','B','C']
# zip后 : [(1,'A'),(2,'B'),(3,'C')]

# 保存数据
def writePage(self):
pass

# 主函数
def workOn(self):
self.getPage("http://maoyan.com/board/4?offset=0")

if __name__ == "__main__":
spider = MaoyanSpider()
spider.workOn()