python网页解析:xpath, css, bs4,pyquery

xml parse 基础

常用库

import re
from lxml import etree
from bs4 import BeautifulSoup
from pyquery import PyQuery
import parsel
import requests
content = requests.get("https://www.baidu.com").text

只简单记录各个库解析html的方式,库的其他功能不记录,PyQuery和scrapy Selectors都是基于lxml模块,而lxml和正则表达式都是C语言写的,只有Beautifulsoup是用纯Python编写的,所以在实测中,Beautifulsoup 的解析速度比其他几种慢了5倍以上!

一、 xpath

1. 基本语法

节点类型:元素、属性、文本、命名空间、处理指令、注释以及文档节点(或称为根节点)。
节点关系: 父(parent), 子(Children), 同胞(Sibling), 先辈(Ancestor), 后代(Descendant)
xpath语法:

# 单个路径:
nodename #选取此节点的所有子节点
. #选取当前节点
.. #选取当前节点的父节点
/  #从根节点开始 /nodename 取当前节点的所有nodename子节点
// #从网页中匹配对应节点,不在乎位置 //nodename 取当前节点的所有的nodename后代节点
div/@class  #获取属性
/div[@attr]  #获取具有某属性的节点 
/div[@attr=value]  #获取具有指定属性值的节点
div/* #通配符 ,匹配所有节点 //div[@*] # 获取所有有属性的div节点
/div[tag] #获取具有指定子孙节点的直接子节点  //div[a] 具有节点a的div节点
/div[last()-1] #获取匹配到的倒数第二个节点
/div[1] # 获取匹配到的第一个节点
/div[position()<3] # 获取前两个节点

# 选取多个路径:
//div/a | //div/p  # 使用或符号'|'来获取多个路径的节点

# 使用轴名索引节点:
轴:ancestor, ancestor-or-self, attribute, child, descendant(后代), descendant-or-self,  
    following(当前节点结束后的所有节点), namespace(当前节点的所有命名空间节点), parent,  
    preceding(当前节点开始之前的所有节点), preceding-sibling(当前节点之前的同级节点), self(当前节点),
语法:轴名::节点名/属性
# child::book  # 选取当前节点的所有book子节点
# ancestor::book # 选取当前节点的所有book祖先节点
# attribute:: * # 当前节点的所有属性
# child::*/child::price # 当前节点的所有子节点的price子节点(当前节点的孙节点)
...

2. python 调用
from lxml import etree
page = etree.HTML("content")
links = page.xpath("//div/@class ")
link1 = page.xpath("child::div/attribute::class")

二、 css

1. 基本语法

id,类选择器:

#id  #id选择器  
.class #类选择器  

标签选择器:

p  #选择所有<p>元素
div,p	#选择所有<div>元素和 <p> 元素
div p	#选择<div>元素内的所有<p>元素
div>p	#选择所有父级是 <div> 元素的 <p> 元素
p.hometown	#选择所有 class="hometown" 的 <p> 元素

属性提取器:

div[attribute]	#选择所有带有attributet属性的div元素	  
div[attribute=value] #选择所有attribute=value的div元素
::attr(attribute)/text # 获取属性 a::text  a::attr(href) # parsel库支持, bs4不支持

其他:

#下面命令是css选择器支持的部分命令但python的parsel和bs4未必支持
:link	a:link	选择所有未访问链接	
:visited	a:visited	选择所有访问过的链接	
:active	a:active	选择活动链接	
:hover	a:hover	选择鼠标在链接上面时	
:focus	input:focus	选择具有焦点的输入元素	
:first-letter	p:first-letter	选择每一个<p>元素的第一个字母	
:first-line	p:first-line	选择每一个<p>元素的第一行	
:first-child	p:first-child	指定只有当<p>元素是其父级的第一个子级的样式。	
:before	p:before	在每个<p>元素之前插入内容	
:after	p:after	在每个<p>元素之后插入内容	
:lang(language)	p:lang(it)	选择一个lang属性的起始值="it"的所有<p>元素
element1~element2	p~ul	选择p元素之后的每一个ul元素	
[attribute^=value]	a[src^="https"]	选择每一个src属性的值以"https"开头的元素	
[attribute$=value]	a[src$=".pdf"]	选择每一个src属性的值以".pdf"结尾的元素	
[attribute*=value]	a[src*="runoob"]	选择每一个src属性的值包含子字符串"runoob"的元素	
:first-of-type	p:first-of-type	选择每个p元素是其父级的第一个p元素	
:last-of-type	p:last-of-type	选择每个p元素是其父级的最后一个p元素	
:only-of-type	p:only-of-type	选择每个p元素是其父级的唯一p元素	
:only-child	p:only-child	选择每个p元素是其父级的唯一子元素	
:nth-child(n)	p:nth-child(2)	选择每个p元素是其父级的第二个子元素	
:nth-last-child(n)	p:nth-last-child(2)	选择每个p元素的是其父级的第二个子元素,从最后一个子项计数	
:nth-of-type(n)	p:nth-of-type(2)	选择每个p元素是其父级的第二个p元素	
:nth-last-of-type(n)	p:nth-last-of-type(2)	选择每个p元素的是其父级的第二个p元素,从最后一个子项计数	3
:last-child	p:last-child	选择每个p元素是其父级的最后一个子级。	
:root	:root	选择文档的根元素	
:empty	p:empty	选择每个没有任何子级的p元素(包括文本节点)	
:target	#news:target	选择当前活动的#news元素(包含该锚名称的点击的URL)	
:enabled	input:enabled	选择每一个已启用的输入元素	
:disabled	input:disabled	选择每一个禁用的输入元素	
:checked	input:checked	选择每个选中的输入元素	
:not(selector)	:not(p)	选择每个并非p元素的元素	
::selection	::selection	匹配元素中被用户选中或处于高亮状态的部分	
:out-of-range	:out-of-range	匹配值在指定区间之外的input元素	
:in-range	:in-range	匹配值在指定区间之内的input元素	
:read-write	:read-write	用于匹配可读及可写的元素	
:read-only	:read-only	用于匹配设置 "readonly"(只读) 属性的元素	
:optional	:optional	用于匹配可选的输入元素	
:required	:required	用于匹配设置了 "required" 属性的元素	
:valid	:valid	用于匹配输入值为合法的元素	
:invalid	:invalid	用于匹配输入值为非法的元素
python调用
import parsel
selector = parsel.Selector("Content")
span = selector.css(query="div")

三、 bs4

from bs4 import BeautifulSoup
text = "" # html字符串  or open("test.html")
soup = BeautifulSoup(text, "lxml")
# 标签查找
first_div = soup.div # 获取指定标签名的第一个标签
soup.find(id="test")
# soup.find(name, attrs, recursive, text, **kwargs) # 按条件搜索节点,返回找到的第一个节点
# soup.find_all(name, attrs, recursive, text, **kwargs) # 返回找到的全部节点
# name: 节点名
# text:查找对应文本,支持正则 soup.find(text=re.compile("10 minutes to pandas.*"))
# attrs: 通过属性来查找标签 soup.find(attrs={'class':"dpn"})/ find(target='_blank') # class是关键字只能用{}形式,
# 支持回调函数查找: soup.find(lambda x: x.has_attr("title"))
# soup.find_next(), soup.find_parent(), soup.findChild()... # 根据节点之间关系查找

# 属性查找
first_div_attrs = soup.div.attrs # 返回所有属性{class:[a, b], id:[c,d]}
div_class = soup.div['class'] #返回第一个div的class属性[a, b]
title_text = soup.title.text # 获取text字符串
a_string = soup.a.string # 获取a的text(应该和.text功能一样,但有可能获取到Comment(注释)对象,从而导致我们获取到文本中夹杂了不需要到注释), .strings 返回一个数组[text1,text2...]
# if type(soup.a.string) == bs4.element.Comment:...   通过判断获取到文本类型是否为注释,进行对应操作,正常文本类型应为bs4.element.NavigableString(可遍历字符串)

# bs4使用css选择器
soup.select("div, p") # bs4支持部分的css选择器


四、 pyquery

pyquery是基于lxml库开发的: res = doc(“css”) -> PyQuery([lxml.html.HtmlElement,…])
res是pyquery.pyquery.PyQuery对象,支持PyQuery的函数,
但PyQuery对象中的元素res[0]是lxml.html.HtmlElement,支持lxml.etree.HTML的函数
pyquery因此使用items()来将res中的元素变成pyquery.pyquery.PyQuery对象

from pyquery import PyQuery
# 初始化
content = "" # html字符串
doc = PyQuery(content) # 根据字符串初始化, 若content不是一个完整的html文件, 初始化时pyquery会自动补全
# doc = PyQuery(url=url, encoding='utf8') # 根据网址初始化doc
# doc = PyQuery(filename=filepath, encoding='utf8') # 根据文件初始化

# 访问节点
title = doc("title") # 直接通过节点名访问节点(css)
img = doc("img[class='logo]")  # 使用css搜索节点
li = doc.find("[target='_blank']")# find(css)
for tag in li.items():
    print(tag.text())  # 若无items(), 则tag为lxml对象,使用tag.text



# 访问属性
text = doc.text # 返回网页中的所有文本字符串/注释/style/script代码等内容 soup.text只返回网页中的文本字符串
tag_text = doc("title").text() # 使用text()访问节点的text属性
tag_id = doc.attr("id") # 使用attr()访问属性

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值