代碼為自學(xué)時所寫呀邢,如有錯誤铺遂,請不吝指教
xpath相關(guān)的基礎(chǔ)語法學(xué)習(xí)
lxml官方文檔介紹
-
lxml的安裝(我用的版本是4.1.1,python 3.5.2)
pip install lxml
//引用(下面是python3的引用格式)
from lxml import etree
-
簡單的創(chuàng)建和遍歷
# 創(chuàng)建
root = etree.Element('root')
# 添加子元素,并為子節(jié)點添加屬性
root.append(etree.Element('child',interesting='sss'))
# 另一種添加子元素的方法
body = etree.SubElement(root,'body')
body.text = 'TEXT' # 設(shè)置值
body.set('class','dd') # 設(shè)置屬性
//
# 輸出整個節(jié)點
print(etree.tostring(root, encoding='UTF-8', pretty_print=True))
//
//
# 創(chuàng)建,添加子節(jié)點腥寇、文本、注釋
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')) # 添加注釋
# 為第三個節(jié)點添加一個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的解析
# 先導(dǎo)入相關(guān)模塊
from lxml import etree
from io import StringIO, BytesIO
# 對html具有修復(fù)標(biāo)簽補全的功能
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') # 返回的是一個數(shù)組
# 獲取第一個的tag
print(h1[0].tag)
# 獲取第一個的class屬性
print(h1[0].get('class'))
# 獲取第一個的文本內(nèi)容
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學(xué)習(xí)
"""
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的內(nèi)容
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.reibang.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.reibang.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"]
# 倒數(shù)第二篇 //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.reibang.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.reibang.com' + article.get('href')))
else:
return articleList
# 獲取瀏覽量大于n的文章的標(biāo)題和地址
def listArticleByFilter(self, printFlag=True, n=1000):
scanList = self.root.xpath('//div[@id="list-container"]//li//div[@class="meta"]/a[1]') # 獲取所有的瀏覽量的 a 標(biāo)簽
if printFlag:
for sc in scanList:
textList = sc.xpath('./text()') # 獲取a 的文本职辅, 文本內(nèi)容基本上均是['\n',' 181\n ']
for txt in textList:
try:
# print(txt)
txt = txt[:txt.index('\n')].strip() # 以\n分割棒呛,并去除前后空格
# print(txt)
scanCount = int(txt) # 轉(zhuǎn)換成int類型
if scanCount > n:
# print(scanCount)
# 獲取 a標(biāo)簽的父元素<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.reibang.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)
# 所有文章的標(biāo)題
lx.listArticleTitle(False)
# 所有文章的鏈接
lx.listArticleHref(False)
# 所有文章的id
lx.listArticleId(False)
# 獲取第三篇文章的title和鏈接
lx.getThirdArticle(False)
# 獲取前三篇文章的title和鏈接
lx.listthreeArticle(False)
# 獲取瀏覽量大于1000的文章
lx.listArticleByFilter(printFlag=False)