python lxml模块中xpath的学习

代码为自学时所写,如有错误,请不吝指教
xpath相关的基础语法学习
lxml官方文档介绍

  • lxml的安装(我用的版本是4.1.1,python 3.5.2)

pip install lxml
//引用(下面是python3的引用格式)
from lxml import etree
  • 简单的创建和遍历

# 创建
root = etree.Element('root')
# 添加子元素,并为子节点添加属性
root.append(etree.Element('child',interesting='sss'))
# 另一种添加子元素的方法
body = etree.SubElement(root,'body')
body.text = 'TEXT' # 设置值
body.set('class','dd') # 设置属性
//
# 输出整个节点
print(etree.tostring(root, encoding='UTF-8', pretty_print=True))
//
//
# 创建,添加子节点、文本、注释
root = etree.Element('root')
etree.SubElement(root, 'child').text = 'Child 1'
etree.SubElement(root, 'child').text = 'Child 2'
etree.SubElement(root, 'child').text = 'Child 3'
root.append(etree.Entity('#234'))
root.append(etree.Comment('some comment'))  # 添加注释
# 为第三个节点添加一个br
br = etree.SubElement(root.getchildren()[2],'br')
br.tail = 'TAIL'
for element in root.iter(): # 也可以指定只遍历是Element的,root.iter(tag=etree.Element)
   if isinstance(element.tag, str):
        print('%s - %s' % (element.tag, element.text))
    else:
        print('SPECIAL: %s - %s' % (element, element.text))
  • 对HTML/XML的解析

# 先导入相关模块
from lxml import etree
from io import StringIO, BytesIO
# 对html具有修复标签补全的功能
broken_html = '<html><head><title>test<body><h1 class="hh">page title</h3>'
parser = etree.HTMLParser()
tree = etree.parse(StringIO(broken_html), parser) # 或者直接使用 html = etree.HTML(broken_html)
print(etree.tostring(tree, pretty_print=True, method="html"))
#
#
#用xpath获取h1
h1 = tree.xpath('//h1')  # 返回的是一个数组
# 获取第一个的tag
print(h1[0].tag)
# 获取第一个的class属性
print(h1[0].get('class'))
# 获取第一个的文本内容
print(h1[0].text)
# 获取所有的属性的key,value的列表
print(h1[0].keys(),h1[0].values())
  • 使用xpath的一个小示例

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

from lxml import etree


class LearnXpath(object):
    """
    python 中 lxml模块的 xpath学习
    """

    def __init__(self, fileName='./example.html'):
        self.htmlParser = etree.HTMLParser(remove_comments=True, compact=True, encoding='UTF-8')
        self.root = etree.parse(fileName, self.htmlParser)

    # 打印html的内容
    def __str__(self):
        return str(etree.tostring(self.root, pretty_print=True, method='html'), encoding='UTF-8')

    __repr__ = __str__

    # 查出头像图片的alt和src, 并去重头像的地址
    def listAuthorImg(self, printFlag=True):
        imgList = self.root.xpath('//div[@id="list-container"]//div[@class="author"]//img')
        s = set()
        if printFlag:
            for img in imgList:
                if img.get('src') in s:
                    continue
                else:
                    s.add(img.get('src'))
                    print('alt=%s, src=%s' % (img.get('alt'), 'http:' + img.get('src')))
        else:
            return imgList

    # 查询图片中,alt>100的所有图片, 并去重
    def listImgAltBig100(self, printFlag=True):
        imgList = self.root.xpath('//div[@id="list-container"]//li//img[number(@alt)>100]')
        s = set()
        if printFlag:
            for img in imgList:
                if img.get('src') in s:
                    continue
                else:
                    s.add(img.get('src'))
                    print('alt=%s, src=%s' % (img.get('alt'), 'http:' + img.get('src')))

    # 获取文章列表的title和链接地址
    def listArticle(self, printFlag=True):
        articleList = self.root.xpath('//div[@id="list-container"]//li//a[@class="title"]')
        if printFlag:
            for article in articleList:
                print('title=%s, src=%s' % ('《'+article.text + '》', 'http://www.jianshu.com'+article.get('href')))
        else:
            return articleList

    # 获取文章名称的列表  在htmlParser中需要指定encoding='UTF-8' ,不然,获取的是乱码
    def listArticleTitle(self, printFlag=True):
        titleList = self.root.xpath('//div[@id="list-container"]//li//a[@class="title"]/text()')
        if printFlag:
            for title in titleList:
                print('《' + title + '》')
        else:
            return titleList

    # 获取文章的所有的链接地址
    def listArticleHref(self, printFlag=True):
        hrefList = self.root.xpath('//div[@id="list-container"]//li//a[@class="title"]/@href')
        if printFlag:
            for href in hrefList:
                print('http://www.jianshu.com'+href)
        else:
            return hrefList

    # 获取文章的id
    def listArticleId(self, printFlag=True):
        idList = self.root.xpath('//div[@id="list-container"]/ul/li/@data-note-id')
        if printFlag:
            for id in idList:
                print(id)

    # 获取第三篇文章的title和链接
    def getThirdArticle(self, printFlag=True):
        # 最后一篇 //div[@id="list-container"]/ul/li[last()]//a[@class="title"]
        # 倒数第二篇 //div[@id="list-container"]/ul/li[last()-1]//a[@class="title"]
        thirdArticle = self.root.xpath('//div[@id="list-container"]/ul/li[3]//a[@class="title"]')
        if printFlag:
            print('title=%s, src=%s' % ('《' + thirdArticle[0].text + '》', 'http://www.jianshu.com' + thirdArticle[0].get('href')))
        else:
            return thirdArticle

    # 获取前三篇文章的title和链接
    def listthreeArticle(self, printFlag=True):
        articleList = self.root.xpath('//div[@id="list-container"]/ul/li[position()<4]//a[@class="title"]')
        if printFlag:
            for article in articleList:
                print('title=%s, src=%s' % ('《' + article.text + '》', 'http://www.jianshu.com' + article.get('href')))
        else:
            return articleList

    # 获取浏览量大于n的文章的标题和地址
    def listArticleByFilter(self, printFlag=True, n=1000):
        scanList = self.root.xpath('//div[@id="list-container"]//li//div[@class="meta"]/a[1]')  # 获取所有的浏览量的 a 标签
        if printFlag:
            for sc in scanList:
                textList = sc.xpath('./text()')  # 获取a 的文本, 文本内容基本上均是['\n',' 181\n        ']
                for txt in textList:
                    try:
                        # print(txt)
                        txt = txt[:txt.index('\n')].strip()  # 以\n分割,并去除前后空格
                        # print(txt)
                        scanCount = int(txt)  # 转换成int类型
                        if scanCount > n:
                            # print(scanCount)
                            # 获取 a标签的父元素<div class="meta"> ,然后再获取该同级元素a[class="title"]
                            titleA = sc.xpath('./ancestor::div[@class="meta"]/preceding-sibling::a[@class="title"]')
                            # print(etree.tostring(titleA[0]))
                            print('scanCount=%d, title=%s, src=%s' % (scanCount, '《' + titleA[0].text + '》', 'http://www.jianshu.com'+titleA[0].get('href')))
                    except:
                        # print(e)
                        continue
        else:
            return 0


if __name__ == '__main__':
    lx = LearnXpath()
    # print(lx)
    # 打印头像图片的大小,以及地址
    lx.listAuthorImg(False)
    # 选取 图片 alt大于100的
    lx.listImgAltBig100(False)
    # 所有文章的title和链接
    lx.listArticle(False)
    # 所有文章的标题
    lx.listArticleTitle(False)
    # 所有文章的链接
    lx.listArticleHref(False)
    # 所有文章的id
    lx.listArticleId(False)
    # 获取第三篇文章的title和链接
    lx.getThirdArticle(False)
    # 获取前三篇文章的title和链接
    lx.listthreeArticle(False)
    # 获取浏览量大于1000的文章
    lx.listArticleByFilter(printFlag=False)

点击获取示例使用的html代码片段

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容