Python爬虫从入门到放弃 05 | Python爬虫打响第一炮之解析网页 - Go语言中文社区

Python爬虫从入门到放弃 05 | Python爬虫打响第一炮之解析网页


此博客仅为我业余记录文章所用,发布到此,仅供网友阅读参考,如有侵权,请通知我,我会删掉。
本文章纯野生,无任何借鉴他人文章及抄袭等。坚持原创!!

前言

你好。这里是Python爬虫从入门到放弃系列文章。我是SunriseCai。

使用Python爬虫就是以下三个步骤,一个步骤对应一篇文章。

  • 请求网页
  • 获取网页响应,解析数据(网页)
  • 保存数据 (未完成

本文章就介绍Python爬虫的第二步:解析网页

  • 主要介绍从HTML文件中提取数据,换句话说就是解析网页。本文章主要介绍以下三种解析网页的方式:
  1. BeautifulSoup
  2. XPath
  3. 正则表达式(re)

查看一下本文章所介绍的三款网页解析方式的区别。

方法 描述
BeautifulSoup 一个可以从HTML或XML文件中提取数据的Python库
XPath 在XML文档中查找信息的语言
正则表达式(re) 一个特殊的字符序列,它能方便的检查一个字符串是否与某种模式匹配。

这里主要介绍一下他们的基本使用,其它更为详细的建议点击上方的链接去系统的学习。


安装模块

首先,需要在cmd窗口输入一下命令,安装本文章所使用到的 bs4lxml 模块。

pip install beautifulsoup4
pip install lxml


1) BeautifulSoup

BeautifulSoup是一款功能非常强大的数据处理工具,它有着四大种类,遍历文档书,搜索文档书,CSS选择器等操作,这里只对它的四大种类以及基本使用做一下简单的介绍。

1.1 BeautifulSoup4四大对象种类

BeautifulSoup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

种类 描述
Tag 理解为HTML中的各个标签
NavigableString 获取标签内的文字
BeautifulSoup 表示文档的全部内容
Comment 过滤注释后的获取标签内文字

1.2 BeautifulSoup 基本使用示例

首先,导入BeautifulSoup模块。

from bs4 import BeautifulSoup

这里上一段操作示例HTML代码:

html_doc = '''
<html>
<body>
<div id='nothing'>
    <ul>
        <li class="animal">
            <a href="www.animal.html" class='one'>小狗</a>
        </li>
        <li class="fruits">
            <a href="www.fruits.html" class='two'>水果</a>
        </li>
        <li class="vegetable">
            <a href="www.vegetable.html class='three'">白菜</a>
        </li>
    </ul>
</div>
</body>
</html>
'''

创建BeautifulSoup对象:

soup = BeautifulSoup(html_doc,'lxml')

基本使用示例:

soup = BeautifulSoup(open("index.html"))	# 创建一个文件句柄的BeautifulSoup对象
soup = BeautifulSoup("<html>data</html>")	# 创建一段字符串的BeautifulSoup对象

print(soup.prettify())		# 格式化输出soup对象

print(soup.li)				# 获取第一个li标签的内容
print(soup.div)			# 获取第一个div标签的内容

print(soup.find('a'))		# 获取文档中第一个 <a> 标签
print(soup.find_all('a'))	# 获取文档中所有 <a> 标签

print(soup.a.string)		# 获取a标签的文字内容
print(soup.get_text())		# 获取文档中所有的文字内容

......
'太多太多的示例无法一一例举,用1万字去写它都不够。'

1.3 BeautifulSoup 四大种类示例

以下示例引用自BeautifulSoup官方文档。但是引用的不完全,建议阅读官方文档进行系统的学习。

1.3.1 Tag

Tag:

soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml')
tag = soup.a
type(tag)	# <class 'bs4.element.Tag'>
  • Tag有很多方法和属性,现在介绍一下tag中最重要的属性:nameattributes

name:

# 通过 .name 来获取tag的名字
print(tag.name)	# 'a'

# 改变tag的name
tag.name = "blockquote"
print(tag)		# <blockquote href="www.animal.html">小狗</blockquote>

attributes:

# 一个tag可能有很多个属性 .tag <b class="boldest"> 有一个 "class" 的属性,值为 "boldest"
print(tag['class'])	# ['one']

# 也可以直接"点"取属性, 比如: .attrs
print(tag.attrs)	# {'href': 'www.animal.html', 'class': ['one']}
--------------------------------------------------------------------
# tag的属性可以被添加,删除或修改。tag的属性操作方法与字典一样
tag['class'] = 'verybold'
tag['id'] = 1
print(tag)			# <a class="verybold" href="www.animal.html" id="1">小狗</a>

del tag['class']	# 删除'class'
del tag['id']		# 删除'id'
print(tag)			# <a href="www.animal.html">小狗</a>

print(tag['class'])		# KeyError: 'class'
print(tag.get('class'))	# None

1.3.2 NavigableString

  • 上面的操作是获取标签的所有内容,现在用**NavigableString **来获取标签里边包含的文字。
# 用.string 即可获取标签内部的文字
soup = BeautifulSoup(html_doc,'lxml')

print(soup.a.string)			# 小狗
print(type(soup.a.string))	# <class 'bs4.element.NavigableString'>

1.3.3 BeautifulSoup

  • BeautifulSoup 对象表示的是一个文档的全部内容,大部分时候,可以把它当作 Tag 对象。
soup = BeautifulSoup(html_doc,'lxml')
print(soup.name)	# [document]

1.3.4 Comment

  • Comment 对象是一个特殊类型的 NavigableString 对象,它输出的内容是过滤掉注释符号的
markup = "<b><!--Hey, buddy. Want to buy a used parser?--></b>"
soup = BeautifulSoup(markup,'lxml')
comment = soup.b.string

print(comment)			# Hey, buddy. Want to buy a used parser?
print(type(comment))	# <class 'bs4.element.Comment'>

这是你想要的吗?我可以保证不是,但是请别着急,官方文档更好用,点击直达BeautifulSoup官方文档。

2) XPath(XML Path Language)

2.1 XPath 介绍

XPath即为XML路径语言(XML Path Language),是一门在 XML 文档中查找信息的语言。这里对XPath的基本使用做一个介绍,建议移步到XPath教程,系统的学习XPath。

下面是最有用的路径表达式:

表达式 用法 描述
nodename xpath(‘//div’) 选取此节点的所有子节点。
/ xpath(‘/div’) 从根节点选取。
// xpath(‘//div’) 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。
. xpath(‘./div’) 选取当前节点。
.. xpath(‘..’) 选取当前节点的父节点。
@ xpath(’/@calss’) 选取属性。

2.2 XPath 基本使用示例

首先是导入模块etree,模块在上面已经安装了,利用XPath进行HTML的解析。

from lxml import etree

etree模块是可以对文本进行补全修正的,用etree.tostring()或者etree.tostringlist(),但是这里的重点不是说它。
下面是用XPath解析网页的相关实例代码:

html_doc = '''
<html>
<body>
<div id='nothing'>
    <ul>
        <li class="animal">
            <a href="www.animal.html" class='one'>小狗</a>
        </li>
        <li class="fruits">
            <a href="www.fruits.html" class='two'>水果</a>
        </li>
        <li class="vegetable">
            <a href="www.vegetable.html class='three'">白菜</a>
        </li>
    </ul>
</div>
</body>
</html>
'''

# 需要先声明一段HTML文本,构造一个XPath解析对象
parse_html = etree.HTML(html_doc)

2.2.1 获取属性

  • 示例:获取<li>标签的class属性
# 获取第一个 <li> 标签的class属性
class_content = parse_html.xpath('//li[1]/a/@href')
print(class_content)	# ['www.animal.html']

# 获取全部 <li> 标签的class属性
class_content =parse_html.xpath('//li/a/@href')
print(class_content)	# ['www.animal.html', 'www.fruits.html', 'www.vegetable.html']

2.2.2 获取文本

  • 示例:获取<a>标签的文本
# 获取第一个 <a> 标签的文本内容
text = parse_html.xpath('//li[1]/a/text()')
print(text)			# ['小狗']

# 获取全部 <a> 标签的文本内容
text = parse_html.xpath('//li/a/text()')
print(text)			# ['小狗', '水果', '白菜']

2.2.3 获取所有节点

  • 示例:获取所有lia节点
# 获取所有 <li> 节点
node = parse_html.xpath('//li')	
print(node)			# [<Element li at 0x2af2b3b3a88>, <Element li at 0x2af2b3b3a48>, <Element li at 0x2af2b3b3b48>]

# 获取所有 <a> 节点
node = parse_html.xpath('//a')
print(node)			# [<Element a at 0x26978ab5a48>, <Element a at 0x26978ab5a08>, <Element a at 0x26978ab5b08>]

2.2.4 获取子节点

  • 示例:获取所有li节点的子节点a的文本内容
child_node = parse_html.xpath('//li/a/text()')
print(child_node)		# ['小狗', '水果', '白菜']

2.2.5 获取父节点

  • 示例:获取所有a节点的父节点liclass属性
parent_node = parse_html.xpath('//a/../@class')
print(parent_node)		# ['animal', 'fruits', 'vegetable']

这是你想要的吗?我猜想不是,但是请别着急,官方文档更好用,点击直达XPath 教程XPath常用语法

3) 正则表达式(re)

首先,建议移步官方文档进行系统的学习正则表达式:https://docs.python.org/3/library/re.html
正则实在是太多东西了,这里担心误人子弟,还请各位参考官方文档去进行系统的学习。

3.1 正则的常用函数

  • 常用方法
方法 语法 描述
re.sub re.sub(pattern, repl, string, count=0, flags=0) 用于替换字符串中的匹配项
re.compile re.compile(pattern, flags=0) 用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match()search() 这两个函数使用。
re.match re.match(pattern, string, flags=0) 从字符起始位置匹配正则表达式,如果不成功则返回None
re.search re.search(pattern, string, flags=0) 匹配字符串并返回第一个成功的匹配,如果不成功则返回None
re.findall re.findall(pattern, string, flags=0) 返回正则表达式匹配的所有符合的内容,如果不成功则返回空列表
re.finditer re.finditer(pattern, string, flags=0) findall 一样,只不过作为迭代器返回匹配的字符串
  • 看到方法中有很多常出现的字眼,如pattern,string,flags=0等,下面对它们做一下介绍。
方法 描述
pattern 匹配的正则表达式
string 待匹配的字符串
flags 标志位,用于控制正则表达式的匹配方式
  • 这里的flags代表什么呢?请看下表。
方法 描述
re.I 忽略大小写
re.L 做本地化识别(locale-aware)匹配
re.M 多行匹配,影响 ^ 和 $
re.S 使 . 匹配包括换行在内的所有字符
re.U 根据Unicode字符集解析字符。这个标志影响 w, W, b, B
re.X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。

在这里插入图片描述

3.2 正则表达式(re)使用示例

首先导入模块。该模块为Python自带,无需另行安装。

import re

下面是用XPath解析网页的相关实例代码:

html_doc = '''
<html>
<body>
<div id='nothing'>
    <ul>
        <li class="animal">
            <a href="www.animal.html" class='one'>小狗</a>
        </li>
        <li class="fruits">
            <a href="www.fruits.html" class='two'>水果</a>
        </li>
        <li class="vegetable">
            <a href="www.vegetable.html" class='three'>白菜</a>
        </li>
    </ul>
</div>
</body>
</html>
'''

3.2.1 re.sub示例

  • 2020SunriseCai的数字替换成 0
result = re.sub('d', '0', '2020SunriseCai')
print(result)	# 0000SunriseCai

3.2.2 re.compile示例

在这里插入图片描述

  • 匹配第一个<> 标签的内容
pattren = re.compile('<.*?>')
result = pattren.search(html_doc)
print(result) # <re.Match object; span=(1, 7), match='<html>'>
print(result) # <html>

3.2.3 re.match示例

  • 匹配字符串2020SunriseCai
# 匹配成功
result = re.match("d+", '2020SunriseCai')
print(result) # <re.Match object; span=(0, 3), match='2020'>
print(result) # 2020

# 匹配不成功 返回None
result = re.match("s+", '2020SunriseCai')
print(result)	# None

3.2.4 re.search示例

  • 匹配第一个a标签
result = re.search("(<a .*?</a>)", html_doc, re.M)
print(result.group()) 
# <a href="www.animal.html" class='one'>小狗</a>

3.2.5 re.findall示例

  • 匹配所有a标签,返回列表
result = re.findall("(<a .*</a>)", html_doc, re.M)
print(result)

# ['<a href="www.animal.html" class='one'>小狗</a>', 
'<a href="www.fruits.html" class='two'>水果</a>', 
'<a href="www.vegetable.html" class='three'>白菜</a>']

3.2.6 re.finditer示例

  • 匹配所有a标签,返回迭代器
result = re.finditer("(<a .*</a>)", html_doc, re.M)
for data in result:
    print(data.group())

# <a href="www.animal.html" class='one'>小狗</a>
# <a href="www.fruits.html" class='two'>水果</a>
# <a href="www.vegetable.html" class='three'>白菜</a>

这是你想要的吗?我猜想不是,但是请别着急,官方文档更好用,点击直达
正则表达式:
https://docs.python.org/3/library/re.html
优秀博文:Python正则表达式详解——re库


不可否认,本篇文章写的很差劲,建议各位点击官方文档的链接过去进行系统的学习。
多个网页解析器总有一款适合你,选择自己喜欢的方式进行系统的学习吧。


最后来总结一下本章的内容:

  1. 介绍了几个网页解析器的基本使用
  2. 介绍了BeautifulSoup的基本使用
  3. 介绍了XPath的基本使用
  4. 介绍了正则表达式 re的基本使用

sunrisecai

  • 感谢你的耐心观看,点关注,不迷路。
  • 为方便菜鸡互啄,欢迎加入QQ群组织:648696280

下一篇文章,名为 《Python爬虫从入门到放弃 06 | Python爬虫打响第一炮之保存数据》

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_45081575/article/details/103975809
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2020-02-02 18:05:49
  • 阅读 ( 1081 )
  • 分类:

0 条评论

请先 登录 后评论

官方社群

GO教程

推荐文章

猜你喜欢