Task3、页面解析 - 解析库的使用

简介: Task3、页面解析 - 解析库的使用

3.1、正则表达式-基本语法


正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。

Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。

re 模块使 Python 语言拥有全部的正则表达式功能。

compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。

re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。

打开开源中国提供的正则表达式测试工具 tool.oschina.net/regex/

输入待匹配的文本,然后选择常用的正则表达式,就可以得出相应的匹配结果了。 例如,输入下面这段待匹配的文本:

www.baidu.com/s?ie=utf-8&…

这段字符串中包含了一个电话号码和一个电子邮件,接下来就尝试用正则表达式提取出来,如图所示。


re.match函数


re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。

import re
print(re.match('www', 'www.baidu.com').span())  # 在起始位置匹配
print(re.match('com', 'www.baidu.com'))         # 不在起始位置匹配
(0, 3)
None


re.search方法


re.search 扫描整个字符串并返回第一个成功的匹配。

import re
print(re.search('www', 'www.baidu.com').span())  # 在起始位置匹配
print(re.search('com', 'www.baidu.com').span())  # 不在起始位置匹配
(0, 3)
(10, 13)


re.match与re.search的区别


re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。

import re
line = "Cats are smarter than dogs";
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print("match --> matchObj.group() : ", matchObj.group())
else:
   print("No match!!")
matchObj = re.search( r'dogs', line, re.M|re.I)
if matchObj:
   print("search --> searchObj.group() : ", matchObj.group())
else:
   print("No match!!")
No match!!
search --> searchObj.group() :  dogs


检索和替换


Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。

import re
phone = "2021-999-888 # 这是一个奇奇怪怪的电话号码"
# 删除字符串中的 Python注释 
num = re.sub(r'#.*$', "", phone)
print("电话号码是 : ", num)
# 删除非数字(-)的字符串 
num = re.sub(r'\D', "", phone)
print("电话号码是 : ", num)
电话号码是 :  2021-999-888 
电话号码是 :  2021999888
import re
# 将匹配的数字乘以 2
def double(matched):
    value = int(matched.group('value'))
    return str(value * 2)
s = 'A23G4HFD567'
print(re.sub('(?P<value>\d+)', double, s))
A46G8HFD1134


re.compile 函数


compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。

pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字
 m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
 print(m)
<_sre.SRE_Match object; span=(3, 5), match='12'>
m.group(0)
'12'
m.start(0)
3
m.end(0)
5
m.span(0)
(3, 5)

在上面,当匹配成功时返回一个 Match 对象,其中:

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))。


findall


在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。


注意: match 和 search 是匹配一次 findall 匹配所有。

import re
pattern = re.compile(r'\d+')   # 查找数字
result1 = pattern.findall('blue 123 google 456')
result2 = pattern.findall('bbb88uuu123google456', 0, 10)
print(result1)
print(result2)
['123', '456']
['88', '12']


re.finditer


和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。

import re
it = re.finditer(r"\d+","12a32bc43jf3") 
for match in it: 
    print (match.group() )
12
32
43
3


re.split


split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

re.split('a*', 'hello world')   # 对于一个找不到匹配的字符串而言,split 不会对其作出分割
['hello world']


其他用法可自行去查找资料学习,这里只做部分常用的介绍使用


3.2、xpath使用


XPath 的选择功能十分强大,它提供了非常简洁明了的路径选择表达式。另外,它还提供了超过 100 个内建函数,用于字符串、数值、时间的匹配以及节点、序列的处理等。几乎所有我们想要定位的节点,都可以用 XPath 来选择。

XPath 于 1999 年 11 月 16 日成为 W3C 标准,它被设计为供 XSLT、XPointer 以及其他 XML 解析软件使用,更多的文档可以访问其官方网站:www.w3school.com.cn/xpath/index…www.runoob.com/xpath/xpath…


XPath 常用规则


表达式   描述

nodename  选取此节点的所有子节点

/   从当前节点选取直接子节点
//  从当前节点选取子孙节点
.  选取当前节点
..  选取当前节点的父节点
@  选取属性
这里列出了 XPath 的常用匹配规则,示例如下:
//title[@lang='eng']

这就是一个 XPath 规则,它代表选择所有名称为 title,同时属性 lang 的值为 eng 的节点。

后面会通过 Python 的 lxml 库,利用 XPath 进行 HTML 的解析


安装lxml库


**pip install lxml **

html文件实例:

这里需要注意的是,上面的HTML 文本中的最后一个 li 节点是没有闭合的,但是 etree 模块可以自动修正 HTML 文本

# 首先导入 lxml 库的 etree 模块
from lxml import etree
# 然后声明了一段 HTML 文本,调用 HTML 类进行初始化,这样就成功构造了一个 XPath 解析对象
html = etree.parse('/home/mw/test.html', etree.HTMLParser())
result = etree.tostring(html)  # 调用 tostring() 方法即可输出修正后的 HTML 代码,但是结果是 bytes 类型。这里利用 decode() 方法将其转成 str 类型
print(result.decode('utf-8'))
---------------------------------------------------------------------------
OSError                                   Traceback (most recent call last)
<ipython-input-28-8a2af1f47b82> in <module>
      2 from lxml import etree
      3 # 然后声明了一段 HTML 文本,调用 HTML 类进行初始化,这样就成功构造了一个 XPath 解析对象
----> 4 html = etree.parse('/home/mw/test.html', etree.HTMLParser())
      5 result = etree.tostring(html)  # 调用 tostring() 方法即可输出修正后的 HTML 代码,但是结果是 bytes 类型。这里利用 decode() 方法将其转成 str 类型
      6 print(result.decode('utf-8'))
src/lxml/etree.pyx in lxml.etree.parse()
src/lxml/parser.pxi in lxml.etree._parseDocument()
src/lxml/parser.pxi in lxml.etree._parseDocumentFromURL()
src/lxml/parser.pxi in lxml.etree._parseDocFromFile()
src/lxml/parser.pxi in lxml.etree._BaseParser._parseDocFromFile()
src/lxml/parser.pxi in lxml.etree._ParserContext._handleParseResultDoc()
src/lxml/parser.pxi in lxml.etree._handleParseResult()
src/lxml/parser.pxi in lxml.etree._raiseParseError()
OSError: Error reading file '/home/mw/test.html': failed to load external entity "/home/mw/test.html"


所有节点


我们一般会用 // 开头的 XPath 规则来选取所有符合要求的节点

result = html.xpath('//*')  # * 选取所有类型的节点
print(result)
result = html.xpath('//li')  # 选取li的节点
print(result)  # 打印所有
print(result[0])  # 打印第一个


子节点


我们通过 / 或 // 即可查找元素的子节点或子孙节点

result = html.xpath('//li/a')  # 通过追加 /a 即选择了所有 li 节点的所有直接 a 子节点
print(result)
result = html.xpath('//ul//a')  # 此处的 / 用于选取直接子节点,如果要获取所有子孙节点,就可以使用 //
print(result)


父节点


查找父节点可以用.. 来实现

result = html.xpath('//a[@href="link4.html"]/../@class')
print(result)


属性匹配


在选取的时候,我们还可以用 @符号进行属性过滤。比如,这里如果要选取 class 为 item-1 的 li 节点

result = html.xpath('//li[@class="item-0"]')
print(result)


文本获取


XPath 中的 text() 方法获取节点中的文本

result = html.xpath('//li[@class="item-0"]/a/text()')
print(result)


属性获取


节点属性 @符号就可以获取节点内部文本

result = html.xpath('//li/a/@href')
print(result)

更多详细操作可自行查阅资料


3.3、某度网站的网页解析


第一步、在制定页面调试浏览器,观察所需的文本内容

第二步、请求页面

import requests
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
}
# 请求参数
params = (
    ('wd', '周杰伦'),
)
response = requests.get('https://www.baidu.com/s', headers=headers, params=params)
# 获取响应过长,只显示部分内容
# print(response.text)

第三步,检查是否有我们要的内容

第四步、导入解析库,解析内容

from lxml import etree 
import re 
html = etree.HTML(response.text)
print(html)

第五步、复制xpath : //*[@id="7"]/div/div[2]/div[1]

result = html.xpath('//*[@id="7"]/div/div[2]/div[1]')
print(result)
result = html.xpath('//*[@id="7"]/div/div[2]/div[1]/text()')
print(result)

我们可以发现,我们所爬取的节点内容不包含span、em节点,所以里面的内容我们没有获取到//*[@id="7"]/div/div[2]/div[1]

result = html.xpath('//*[@id="7"]/div/div[2]/div[1]/span/text()')
print(result)  # 输出的是列表格式
print(''.join(result))  # 转化为str格式
print(re.sub("小时前","", ''.join(result)))  # 除去多余
result = html.xpath('//*[@id="7"]/div/div[2]/div[1]/em/text()')  # 获取了所有的节点的周杰伦
print(result)
result = html.xpath('//*[@id="7"]/div/div[2]/div[1]/em[1]/text()')  # 获取了第一个节点的周杰伦
print(result)


Task3、作业


目标网站: 123.meibp.com/tag/%e6%af%…

目标:只需要能够正常提取出来既可以,并在Makrdown运行后,截图出运行内容既可

!! 温馨提示,该项目只作为练习,切勿做出对目标网站有所压力的行为

import requests
from lxml import etree 
import re 
# 请求头
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.63 Safari/537.36',
}
response = requests.get('http://123.meibp.com/tag/%e6%af%8f%e6%97%a5%e7%83%ad%e7%82%b9%e5%85%b3%e9%94%ae%e8%af%8d', headers=headers)
# 获取响应过长,只显示部分内容
html = etree.HTML(response.text)
article_len=len(html.xpath('//*[@id="hot"]/div/div/article'))
print(article_len)
for i in range(1,article_len+1):
    print(25*'*' + str(i) +25*'*')
    title=html.xpath(f'//*[@id="hot"]/div/div/article[{i}]/header/h2/a/text()')
    print('1.标题:',title[-1])
    # 分类显示为空:
    xw_class=html.xpath(f'//*[@id="hot"]/div/div/article[{i}]/span[1]/span/text()')
    print('2.分类:',xw_class[-1])
    mark=html.xpath(f'//*[@id="hot"]/div/div/article[{i}]/span[2]/span/a/text()')
    print('3.标签:',mark)
10
*************************1*************************
1.标题:  每日热点 - 星网大数据
2.分类: 分类: 
3.标签: ['百度', '搜狗', '新浪', '大数据', '热点', '热搜', '关键词', '数据', '榜单', '狗', '每日热点', '百度热搜', '–', '星网大数据', '每日热点关键词']
*************************2*************************
1.标题:  星网大数据 - 汇聚全网词库
2.分类: 分类: 
3.标签: ['大数据', '热点', '关键词', '数据', '分析', '行业词库', '词库', '关键词分析', '企业信用', '企业', '每日热点', '星网大数据', '汇聚全网词库', '关键词库', '全网词库']
*************************3*************************
1.标题:  微友助手-微信群管家
2.分类: 分类: 
3.标签: ['微友助手', '微群管家', '微信管家', '微信群管理', '移动互联网', '微信群', '微信群数据', '消息群发', '微商', '电商', '淘宝客', '自动回复', '客服助手', '微信助手', '微友课堂', '微信多群直播', '社群营销', '安全稳定国内领先微信群管家', '超群助手']
*************************4*************************
1.标题:  爱微帮-每日热点
2.分类: 分类: 
3.标签: ['新媒体', '新媒体运营', '素材', '爱微帮', '热点', '素材库', '运营工具', '媒体', '运营', '新闻热点', '历史上的今天', '选题', '互动', '每日热点', '选题素材库', '爱微帮公众号助手', '微博热搜', '微博热议', '百度热搜', '节日大全', '未来头条']
*************************5*************************
1.标题: 库
2.分类: 分类: 
3.标签: ['关键词', '行业词库', '长尾', '词库', '词库网', '热门关键词库', '长尾关键词库', '网站关键词库', '行业关键词库', '热门词库', '关键词词库', '长尾关键词', '关键词分析', '关键词优化', '关键词排名', '热门关键词', '最新关键词', '行业关键词', '关键词预测']
*************************6*************************
1.标题: 排名查询 卖家店铺优化工具箱
2.分类: 分类: 
3.标签: ['电子商务', '关键词', '电商', '互联网电商', '关键词排名', '卖家', '排名', '天猫', 'im', '工具箱', '查排名', '直通车', '淘宝', '宝贝关键词排名查询', '卖家店铺优化工具箱', '淘宝关键词排名查询', '淘宝宝贝排名查询', '卖家工具箱', '淘宝关键词优化', '直通车优化']
*************************7*************************
1.标题:  抽屉新热榜-聚合每日热门、搞笑、有趣资讯
2.分类: 分类: 
3.标签: ['微博', '图片', '门户', '资讯', '社区', '新闻', '段子', '搞笑', '榜单', '用户', '抽屉', '抽屉新热榜', '聚合每日热门', '有趣资讯', '公众场合不宜', '节操']
*************************8*************************
1.标题:  UC热点
2.分类: 分类: 
3.标签: ['实时', '热点', '实时热点', 'U', 'UC热点']
*************************9*************************
1.标题:  AnyKnew - 全网热点
2.分类: 分类: 
3.标签: ['AnyKnew', '效率资讯', '高效读新闻', '5分钟遍历全网热点']
*************************10*************************
1.标题:  微博热点
2.分类: 分类: 
3.标签: ['微博热点']


目录
相关文章
|
2月前
|
数据采集 JSON 数据可视化
利用R语言和curl库实现网页爬虫的技术要点解析
利用R语言和curl库实现网页爬虫的技术要点解析
|
2月前
|
算法 Linux 开发者
CMake深入解析:打造高效动态链接库路径设置
CMake深入解析:打造高效动态链接库路径设置
52 0
|
2月前
|
算法 数据处理 开发者
FFmpeg库的使用与深度解析:解码音频流流程
FFmpeg库的使用与深度解析:解码音频流流程
42 0
|
2月前
|
XML 前端开发 数据格式
请描述如何使用`BeautifulSoup`或其他类似的库来解析 HTML 或 XML 数据。
【2月更文挑战第22天】【2月更文挑战第67篇】请描述如何使用`BeautifulSoup`或其他类似的库来解析 HTML 或 XML 数据。
|
2月前
|
Java 调度 Python
深入解析 Python asyncio 库:如何使用线程池实现高效异步编程
深入解析 Python asyncio 库:如何使用线程池实现高效异步编程
84 0
|
2月前
|
缓存 算法 C语言
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
【C++ 标准查找算法 】C++标准库查找算法深入解析(In-depth Analysis of C++ Standard Library Search Algorithms)
49 0
|
2天前
|
XML JavaScript 数据格式
Beautiful Soup 库的工作原理基于解析器和 DOM(文档对象模型)树的概念
Beautiful Soup 使用解析器(如 html.parser, lxml, html5lib)解析HTML/XML文档,构建DOM树。它提供方法查询和操作DOM,如find(), find_all()查找元素,get_text(), get()提取信息。还能修改DOM,添加、修改或删除元素,并通过prettify()输出格式化字符串。它是处理网页数据的利器,尤其在处理不规则结构时。
7 2
|
18天前
|
存储 算法 程序员
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
|
1月前
|
存储 JSON JavaScript
【嵌入式开源库】cJSON的使用,高效精简的json解析库
【嵌入式开源库】cJSON的使用,高效精简的json解析库
|
2月前
|
Kubernetes 网络协议 定位技术
阿里云DNS常见问题之IP地理位置库功能开通失败如何解决
阿里云DNS(Domain Name System)服务是一个高可用和可扩展的云端DNS服务,用于将域名转换为IP地址,从而让用户能够通过域名访问云端资源。以下是一些关于阿里云DNS服务的常见问题合集:

推荐镜像

更多