今天主要是复习了css与xpath选择器,以及Beautifulsoup,lxml,pyquery三个解析库,准备用2-3个blog来记录
话不多说进入正题
1.因为在我们提取网站信息的时候,常常都是用正则表达式,而正则表达式经常容易写错,所以我们可以通过每一个标签的id以及class属性来定位他(通常class与id属性都是唯一的)
Xpath
介绍:全称为XML Path Language(XML路径语言),原本用来搜寻XML文档的,但是也适用于HTML文档(XML文档似乎也是用一个个标签写出来的,而且QQ卡片消息好像就是用XML写的,类似于Web搭建吧)
规则:
- nodename:选取这个节点的所有子节点
- /:从当前节点选取其子节点
- //:从当前节点选取其子孙节点
- .:选取当前节点
- …:选取当前节点的父节点
- @:选取当前节点的某些属性(例:[@href=‘aaa’]
示例
//title[@herf=‘aaa’]
这代表选择所有的title节点,且其herf属性为aaa
导入html代码
from lxml import etree
text=’xxxxxxx’
html=etree.HTML(text)
print(etree.tostring(html).decode(‘utf-8’))
从文件里编写html代码
from lxml import etree
htlml=etree.parse(‘a.html’,HTMLParser())
print(etree.tostring(html).decode(‘utf-8’))
因为不会用这个手机代码功能(每次打出div节点就会被转义,所以就不放出html代码了,本博客代码为《python网络爬虫开发实战》-崔庆才中P160的代码
找其中的一个节点
from lxml import etree
html=etree.paser(‘a.html’,HTMLParser())
result=html.xpath(‘//ul//li’)
otherresult=html.xpath(‘/div/ul/li’)
print(result,otherresult,sep=‘\n’)
第一行和第二行都会打印出所有的li节点,但第一个为绝对路径(一个一个节点往里面找),另一个为相对路径(直接跨着找)
找所有节点
from lxml import etree
html=etree.parse(‘a.html’,HTMLParser())
result=html.xpath(‘//*’)
所有html的最大祖先节点都是etree.parse对象,对象的子节点为整个html代码
获取父节点
from lxml import etree
text=‘xxxxxxxxxxxxxx’
html=etree.HTML(text)
result=html.xpath(‘/div/ul/li[@class=‘item-incative]/a/…/@class’)
或
from lxml import etree
html=etree.parse(‘a.html’,’HTMLParser())
result=html.xpath(‘/div/ul/li[3]/parent::*/@class’)
此代码输出的是class=‘item-incative’节点的class属性的值
猜测:parent::* 是否可以替换成parent::[@class=’item-incative‘]
获取文本
获取item-inactive中的a节点文本
from lxml import etree
text=‘xxxxxxxxx’
html=etree.HTML(text)
result=html.xpath(‘/div/ul/li[3]/a/text()’)
或
from lxml import etree
html=(‘a.html’,’HTMLParser())
result=html.xpath(//a[@href=‘link3.html’]/text()
两者打印出来都是href属性为link3.html的a节点中的文本,但是一个为绝对路径,一个为相对路径,且一个为通过变量导入html代码,一个为通过文件导入html代码
属性的获取
from lxml import etree
text=‘xxxxxxxxx’
html=etree.HTML(text)
result=html.xpath(‘/div/ul/li[@class=‘item-inactive’]//a/…/a/parent::*/@class
该代码会打印出li节点的class属性,即item-inactive
属性多值匹配
from lxml import etree
hrml=etree.parse(‘a.html’,HTMLParser())
result=html.xpath(‘//li[contains(@class,’li’)]/a/text()’)
class=“li li-first”,且其中有一个a节点,里面的文本为first item
多属性匹配
若出现多属性节点,例如有一个name=‘aaa’且class=‘a b’的节点,可以用如下方式匹配
from lxml import etree
text=‘xxxxxxxx’
html = etree.HTML(text)
result=html.xpath(‘//li[contains(@class,’b’) and @name=‘aaa’]/text()’)
输出应为li节点下的整个a节点
其他的运算符
1.or:或
2.and:与
3.mod:相除余数
4.|:计算节点集,例如://book|//cd
5.+;-:*;div:加减乘除
6.=:等于
7.!=:不等于
8.<:小于
9.<=:小于等于
10.>:大于
11.>=:大于等于
排序选择
postion(),last()
例:
from lxml import etree
html=etree.parse(‘a.html’,’HTMLParser()’)
result=html.xpath(‘div/ul/li[@class=‘item-0’]/a/text()’)
result=html.xpath(‘div/ul/li[position()<4 and position()>2]/a/text()’]
result=html.xpath(‘div/ul/li[last()-2]/a/text()’]
三个result变量等价,代码在166P
节点轴的选择
ancestor,attribute,child,descendant,following,following-sibling等
from lxml import etree
text=‘xxxxxxxxxxxxxx’
html=etree.HTML(text)
result=html.xpath(‘//li[1]/ancestor::div’)找出所有祖先节点,并从中找第一个div节点
result=html.xpath(‘//li[3]/attribute::’)找出原节点,并打印出它所有的属性值
result=html.xpath(‘//li[3]/child::a[@href=‘link.html’]’)从原节点中找所有子节点,并找href属性为link.html的a节点
result=html.xpath(‘//li[1]/descendant::span/text()’)选择原节点中的所有子孙节点,且从中找出span节点,并打印它的文本
result=html.xpath(‘//li[1]/following::span/text())从原节中往里选择,直到选择到span节点
result=html.xpath(‘//[1]/following-sibling::li[@class=‘item-0’]’)选择兄弟节点中的li节点,且其class属性为item-0