python lxml包用于解析XML和html文件,可以使用xpath和css定位元素,个人认为相对于BeautifulSoup功能更加强大,更加灵活。本文根据lxml官方文档和自己的理解列出常用的函数, 本文代码为python3.4, lxml2.0
lxml:http://lxml.de/
支持:python2 python3
导入xml字符串有多种方式,我最长使用的是 lxml.etree.XML(xml字符串), etree.fromstring(xml字符串)也可以
import lxml.etree
import urllib.request
from lxml.etree import *
str_url = 'http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed&id=26693255&retmode=text&rettype=xml'
request = urllib.request.Request(str_url)
xml_text = urllib.request.urlopen(request).read()
root = lxml.etree.XML(xml_text) # xml_text 为xml纯文本文件
root 为lxml.etree._Element 对象,含有多个函数
root 含有find,findall, xpath,get,getchildren函数, 重点请help(root)
### findall, find
findall(…)
| findall(self, path, namespaces=None)
|
| Finds all matching subelements, by tag name or path.
| 输入下一级对象的tag标签或xpath(必须是相对路径.//开头),返回匹配结果的所有元素,是一个list
| The optional namespaces
argument accepts a
| prefix-to-namespace mapping that allows the usage of XPath
| prefixes in the path expression.
find(…)
| find(self, path, namespaces=None)
|
| Finds the first matching subelement, by tag name or path.
| 输入下一级的tag标签或xpath,返回匹配结果的第一个元素
| The optional namespaces
argument accepts a
| prefix-to-namespace mapping that allows the usage of XPath
| prefixes in the path expression.
# example 获取杂志名称和ISSN
# 使用 tag作为输入需要逐级进行
journal_name = root.find('PubmedArticle').find('MedlineCitation').find('Article').find('Journal').find('Title').text
print('tag:', journal_name)
tag: Cognitive computation
# 也可以使用xpath(必须使用相对路径,以.//开头,如果想使用绝对路径可以使用xpath函数)
journal_name = root.find('.//Title').text
print('xpath:' ,journal_name)
xpath: Cognitive computation
# text是element对象的属性,可以得到内部的内容,如果要得到标签内部的属性
#使用get函数
# 比如得到 1866-9956 的 IssnTYpe属性,则可以使用get函数
issn_attr = root.find('.//ISSN').get('IssnType')
print('issn attr:', issn_attr)
issn attr: Print
# 使用tostring函数
# 可以得到改标签下的全部内容,tostring函数是 lxml.etree 下的静态函数,使用前需要 from lxml.etree import *
tostring(root.find('.//JournalIssue')) # 得到JournalIssue标签下的全部内容
b'\n 7 \n 6 \n \n 2015 \n \n \n '
具体xpath的学习可以参考 http://www.w3school.com.cn/xpath/xpath_syntax.asp
xpath与findall类似也返回一个list,不同之处是只能使用xpath,而且可以使用xpath的相对路径和绝对路径
journal_name = root.xpath('//Title')[0].text
print(journal_name)
Cognitive computation
得到所有直接子元素
注意,使用findall,find,xpath时一定要确定元素是否存在(可以用 if 判断),然后才读取text属性,否则会遇到 Type ‘NoneType’ cannot be serialized., list index out of range, ‘NoneType’ object has no attribute ‘text’这样的错误。
除了上述读取的函数,lxml还包含了很多设置的函数,功能强大,具体可以去看lxml官方文档
http://movie.douban.com/
import lxml.html
str_url = 'http://movie.douban.com/'
request = urllib.request.Request(str_url)
html_text = urllib.request.urlopen(request).read()
root = lxml.html.fromstring(html_text)
# 获取本页面所有项目名称
movies_list = [a.text for a in root.cssselect('div.billboard-bd tr td a')]
print(movies_list)
['老炮儿', '八恶人', '卡罗尔', '海街日记', '荒野猎人', '寻龙诀', '丹麦女孩', '龙虾', '边境杀手', '实习生']
# 获取所有电影超链接
movies_href = [a.get('href') for a in root.cssselect('div.billboard-bd tr td a')]
print(movies_href)
['http://movie.douban.com/subject/24751756/', 'http://movie.douban.com/subject/25787888/', 'http://movie.douban.com/subject/10757577/', 'http://movie.douban.com/subject/25895901/', 'http://movie.douban.com/subject/5327268/', 'http://movie.douban.com/subject/3077412/', 'http://movie.douban.com/subject/3071604/', 'http://movie.douban.com/subject/20514947/', 'http://movie.douban.com/subject/25881247/', 'http://movie.douban.com/subject/10594965/']
text_content() 可以返回改element下的所有文本(去除所有<>标签)
.make_links_absolute(base_href, resolve_base_href=True) 有时候遇到的链接是相对路径,可以使用该函数将相对路径转换为绝对路径
.rewrite_links(link_repl_func, resolve_base_href=True, base_href=None)根据替换函数替换链接