爬虫08:xpath解析

爬虫•目录 爬虫•类别


xpath解析

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

xpath工具

Chrom插件 Xpath Helper

打开 ctrl + shift + x

Firefox插件 Xpath checker

选取节点

  • 路径表达式
表达式 描述
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
  • | 多路径匹配(或)
    xpath表达式1 | xpath表达式2
路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。
  • 函数
    • contains() 匹配一个属性值中 包含某些字符串的节点
      //title[contains(@lang, ‘e’)] 获取节点对象
    • text() 获取文本
      //title[contains(@lang, ‘e’)]/text() 获取的是节点内容

使用

  • 导模块
    from lxml import etree
  • 创建解析对象
    parseHtml = etree.HTML(html)
  • 调用xpath
    rList = parseHtml.xpath(‘xpath表达式’)

    调用xpath,返回的一定为列表

xpath解析例子

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>
'''

# 创建解析对象
paresHtml = etree.HTML(html)

# 调用xpath返回结果
def xp(x):
    rList = paresHtml.xpath(x)
    print(rList)

xp('//ul//a/text()')
#Out:['国内', '国际', '军事', '图片', '社会', '娱乐', '科技', '体育', '财经', '汽车']
xp('//ul/li/a/@href')
#Out:['http://domestic.firefox.sina.com/', 'http://world.firefox.sina.com/', 'http://mil.firefox.sina.com/', 'http://photo.firefox.sina.com/', 'http://society.firefox.sina.com/', 'http://ent.firefox.sina.com/', 'http://tech.firefox.sina.com/', 'http://sports.firefox.sina.com/', 'http://finance.firefox.sina.com/', 'http://auto.firefox.sina.com/']

爬虫案例

抓取目标图片

思路

模特链接列表 = parseHtml.xpath('..')
for 模特链接 in 模特链接列表:
    图片链接列表 = 对模特发请求后xpath
    for 图片链接 in = 图片链接列表:
        html = 对图片连接发请求
        with open(filename, 'wb') as f:
            f.write(html)

步骤
1.获取主页URL,寻找URl规律
http://www.tmt001.com/
2.xpath
List : //div[@class=’result_models’]/ul/li/div[@class=’model_data’]/a/@href
name : //div[@class=’result_models’]/ul/li/div[@class=’model_data’]/a/text()
jpgList ://dd/img/@src
jpgname : name+01

爬虫代码

from lxml import etree
import requests
import time

class TotSpider(object):
    def __init__(self):
        self.baseurl = 'http://www.tmt001.com/'
        self.headers = {'User-Agent':''} 

    def getPage(self, url, xp=None):
        res = requests.get(url=url, headers=self.headers)
        if xp == None:
            return res.content
        res.encoding = 'utf-8'
        html = res.text
        return self.parsePage(html, xp)

    def parsePage(self, html, xp):
        paresHtml = etree.HTML(html)
        rList = paresHtml.xpath(xp)
        return rList

    def writeJpg(self, html, filename):
        with open(filename, 'wb') as f:
            f.write(html)

    def workOn(self):
        menu = '''
        \033[32m********************
        ---    1.爬取    ---
        ---    2.退出    ---
        ********************
        请选择(1/2):\033[0m
        '''
        cmd  = input(menu)
        if cmd.strip() == '1':
            n = input('请输入页数>>>')
            if n.strip().isdigit():
                n = int(n)
                for page in range(1, n+1):
                    url =self.baseurl + '?c=article&a=search&xb=2&page=' + str(page)
                    xp_a = "//div[@class='result_models']/ul/li/div[@class='model_data']/a/@href"
                    xp_name = "//div[@class='result_models']/ul/li/div[@class='model_data']/a/text()"
                    rList_a = self.getPage(url, xp_a)
#                    print(rList_a)
                    rList_name = self.getPage(url, xp_name)
                    for rt_a, filename in zip(rList_a, rList_name):
                        url = self.baseurl + rt_a
                        xp = '//dd/img/@src'
                        rList_jpg = self.getPage(url, xp)
                        for name, rt_j in enumerate(rList_jpg):
                            url = self.baseurl + rt_j
                            html = self.getPage(url)
                            file_name = 'tot/' + filename + str(name) + '.jpg'
                            self.writeJpg(html, file_name)
                            time.sleep(0.2)      
        else:
            print('over')


if __name__ == '__main__':
    spider = TotSpider()
    spider.workOn()

博主个人能力有限,错误在所难免.
如发现错误请不要吝啬,发邮件给博主更正内容,在此提前鸣谢.
Email: JentChang@163.com (来信请注明文章标题,如果附带链接就更方便了)
你也可以在下方的留言板留下你宝贵的意见.


上一篇
爬虫09:动态加载网站数据抓取 爬虫09:动态加载网站数据抓取
爬虫•目录 爬虫•类别 动态加载网站数据抓取 滚动鼠标滑轮时加载的内容抓取浏览器F12 Network->QueryStringParameters 豆瓣电影的抓取import requests import pymysql i
2019-01-22
下一篇
爬虫07:requests请求模块2 爬虫07:requests请求模块2
爬虫•目录 爬虫•类别 Post方法 requests.Post()post()参数 data Form表单数据,字典形式,不需要编码和转码 其它参数同GET() 案例(有道翻译) 抓包,多抓几次观察Form表单中的数据变化(浏览
2019-01-22
目录