【python 爬虫】BeautifulSoup4 库的介绍使用

有部分内容为北理嵩天老师的爬虫教程的个人学习笔记,结合其他博客整理学习。

前言:信息标记形式

html是将声音、图像、音频嵌入到文本中,是Internet上的主要信息组织、传递形式,通过预定义的标签< >…</ >将不同类型的信息组织起来。国际上标准的信息标记形式有XML JSON YAML 三种。

XML 扩展标记语言

标签形式类似html,应用在Internet主流信息交互和传递。
有内容有一对儿标签加内容属性< name>…< /name>,无内容直接省略用一对肩括号表示< name />。可加注释。
实例:

< title>标题名< /title>
< body>数值为多少< /body>

JSON

JavaScript面向对象属性。用在程序对接口处理的地方,经过传输后作为代码的一部分,并被程序直接运行,才可以发挥它数据类型的意义和优势。
属于有数据类型的键(key)值(value)对。

“name”:“王老五”

一个键可能对应多个值,用 [ ] 表示

“name” : [“王老五”,“王老六”]

键值对可以嵌套使用。把键值对放进新键值对的值部分,用 { } 表示。

“key” : { “zikey” : [ “w” , “z”] }

采用有类型的键值对,里面的值是数字类型时就不用加 " " 符号
实例:
在这里插入图片描述

YAML

无 ‘’ ‘’ 引号的键值对形式,一般用在系统配置文件,有注释,简单易读。
用 缩进 表示 所属关系

name :
      value

key:
    zikey : value

用 - 减号表示 value 值的并列关系。
用 # 表示注释

name: #comment
    -王老五
    -王老六

在这里插入图片描述

提取网页中信息标记的几种方式

1、完全解析标记形式,再去按标记提取关键信息。(准确、繁琐、速度慢)
2、无视标记形式,直接进行搜索。(过程简单,快、提取结果准确性不好)
3、两种方法结合。
实例:寻找一个页面内包含的所有url链接。

#BS4openfile.py
from bs4 import BeautifulSoup
html = '''
<html><head><title>This is a python demo page</title></head>
    <body>
    <p class="title"><b>The demo python introduces several python courses.</b></p>
    <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
    <a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>
    </body></html>
    '''
soup = BeautifulSoup(html,"html.parser")
for link in soup.find_all('a'):
    print(link.get('href'))
>>>
	http://www.icourse163.org/course/BIT-268001
	http://www.icourse163.org/course/BIT-1001870001

1、安装

该第三方库可以对html 和 xml 页面进行解析,提取相关信息。
管理员权限启动cmd命令,使用pip 安装BeautifulSoup4

pip install BeautifulSoup4

获取一个html页面,并对它进行beautifulsoup解析。

import requests
from bs4 import BeautifulSoup
#调用时将BeautifulSoup4库缩写为bs4进行调用,若为pycharm环境需要再安装一下bs4包

r = requests.get("http://python123.io/ws/demo.html")
print(r.text)
demo = r.text
soup = BeautifulSoup(demo, "html.parser")  #后面参数为解释器类型,需要其他时需单独安装
#soup =  BeautifulSoup(open("文件.html"), "html.parser") #打开保存在本地的html文件形式
print(soup.prettify())  #prettify()方法为文本内容增加换行符,属于一种格式化的输出方法

其他解析器:
在这里插入图片描述

2、基本元素

html文件中的内容由肩括号和具体的标签以及标签属性构成,属性由键值对表示。
在这里插入图片描述
BS4库的基本元素:
在这里插入图片描述
以一段html代码为例,我们打开上面出现的网址:https://python123.io/ws/demo.html ,右键查看源代码:

<html><head><title>This is a python demo page</title></head>
<body>
<p class="title"><b>The demo python introduces several python courses.</b></p>
<p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a href="http://www.icourse163.org/course/BIT-268001" class="py1" id="link1">Basic Python</a> and <a href="http://www.icourse163.org/course/BIT-1001870001" class="py2" id="link2">Advanced Python</a>.</p>
</body></html>

2.1 Tag标签

以指定的解析器打开上面的网页源代码:

#BS4openfile.py
from bs4 import BeautifulSoup
html = '''
那段源代码
    '''
soup = BeautifulSoup(html,"html.parser")
print(soup.prettify())  #格式化输出

输出显示:

========== RESTART: D:/MathElectric/python/BS4openhtml.py ===============
<html>
 <head>
  <title>
   This is a python demo page
  </title>
 </head>
 <body>
  <p class="title">
   <b>
    The demo python introduces several python courses.
   </b>
  </p>
  <p class="course">
   Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
   <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
    Basic Python
   </a>
   and
   <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">
    Advanced Python
   </a>
   .
  </p>
 </body>
</html>
>>> 

这里面 < html>… < /html>、< body>…< /body>、< p>…< /p>、< a>…< /a>都是标签。

2.2 标签名

打印显示html的指定标签时:

print(soup.title) ##显示全部标签
>>> <title>This is a python demo page</title>

print(soup.tag)
print(soup.tag.name)  #只获取标签名
print(soup.title.name)
>>> title 

标签存在一级一级包含关系,如title标签就在head标签内,head标签就是title标签的父标签。获取某标签的父标签及其父标签的名字:

print(soup.title.parent)
>>>
	<head><title>This is a python demo page</title></head>  #注意显示的是整个标签全部

print(soup.title.parent.name)  #仅显示标签名
>>> 
	 head

2.3 标签属性

标签的属性:

print(soup.p.attrs)  #返回一个 字典 包含所有属性
>>>
 	{'class': ['title']}
print(soup.p.attrs['class']) #也可以单独取某个属性,还可以对属性进行修改、删除
>>>
	['title']
soup.p.attrs['class'] = "NewClass"

2.4 标签内容string

标签的string 属性:NavigableString , 显示标签的内容

print(soup.title.string) #显示标签的具体内容
>>>
	This is a python demo page

2.5 标签的注释

标签的comment注释:

from bs4 import BeautifulSoup
newsoup = BeautifulSoup("<b><!--This is a comment--></b><p>This is not a comment</p>", "html.parser")
newsoup.b.string
》
	'This is a comment'
newsoup.p.string
》
	'This is not a comment'
type(newsoup.b.string)
》
	<class 'bs4.element.Comment'>
type(newsoup.p.string)
》
	<class 'bs4.element.NavigableString'>

两种不同类型的标签在打印的时候并没有标注说明,去掉了注释的 !---- 符号,但是字段的数据类型是不同的,需要注意。

3、HTML 的信息遍历

这是一种树形结构的文本信息。
在这里插入图片描述
在这里插入图片描述

3.1、上行遍历

parent 属性和 parents 属性

parent 是当前节点的父标签,parents 是所有的父辈们的标签。
打印parent是输出标签,parents是一个需要遍历输出的类
遍历 p 标签的父辈们,并显示标签名:

for parent in soup.p.parents:
    if parent is None:
        print(parent)
    else:
        print(parent.name)
>>>
		body
		html
		[document]

html 是顶级标签,父标签为自己,soup 的先辈不存在.name信息

3.2、下行遍历

contents 属性

子节点的列表,将标签的所有 子 节点存入 列表。包含换行符等。

print(soup.body.contents)
>>>
	['\n', <p class="title"><b>The demo python introduces several python courses.</b></p>, '\n', <p class="course">Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a> and <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>.</p>, '\n']

print(len(soup.body.contents))  #获取子节点的数量
>>> 
	5

因为是列表类型,所以列表的常规操作可以使用。

children 属性。

子节点的遍历操作:因为对象不是一个列表,所以不能直接打印输出。

for child in soup.body.children:
    print(child)
    print("**")
print("===================")    

descendants 属性

所有的子孙节点进行遍历,和contents与children不同的地方在于上面两个属性只是与body直接相关的,而descendants是所有的子孙节点都包含。

for desc in soup.body.descendants:
    print(desc)
    print("*****")

3.3、平行遍历

平行遍历的前提是所有的节点在同一个父亲节点之下,否则不能构成平行遍历关系。

next_sibling 属性

返回按照html文本顺序的下一个平行节点(标签)

print(soup.a.next_sibling)
print(soup.a.next_sibling.next_sibling)
>>>
	and
	<a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>

previous_sibling 属性

上一个节点。

next_siblings 属性

迭代类型,需遍历,按照文本顺序后续的所有。

previous_siblings 属性

迭代类型,所有前续的平行节点。

4、基于BS4库的常用Html内容查找方法

在soup变量中查找相关信息,
通常将<标签>.find__all(…)简写为<标签>(…)
将soup.find_all(…)简写为 soup(…)

4.1、典型方法详细介绍

<>.find_all(name,attrs,recursive,string,**kwargs)

4.1.1 name参数

根据标签名称检索相应字符串,返回包含被检索标签的所有标签列表

print(soup.find_all('a'))
》》
	[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

也可以同时查找显示多种标签 a 和 b 及c :

soup.find_all(['a','b','c'])

当 name 参数为True 时,显示soup所有标签的信息。

for tag in soup.find_all(True):
    print(tag.name)
》》
	    html
	    head
	    title
	    body
	    p
	    b
	    p
	    a
	    a

结合正则表达式(Re)库只查找显示包含某个字母或单次的所有标签
import re
soup.find_all(re.compile(‘b’))
只查找和 b 相关的,输出为b 和 body的标签信息。

4.1.2、attrs

表示对标签的属性进行字符串检索,可以查看带有某个属性的标签。

soup.find_all('p','course')
#查找返回 p 标签内的包含 course 属性信息的标签

查找确定的内容信息:注意输入时不使用精确查找会匹配不到

print(soup.find_all(id='link1'))  #精确
print('*****')
print(soup.find_all(id='link'))  #不精确
》》
	[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>]
	*****#上、下为精确和不精确匹配的输出
	[]

想不精确,查找带某个关键词的时候使用正则表达式

soup.find_all(id=re.compile('link'))
》》
	******
	[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]

4.1.3 recursive

表示是否对子孙全部节点检索,默认为True,若只对当前节点的 子节点搜索,则更改为False
对比一下两种表达式的输出差别:

soup.find_all('a')  #全部子孙节点
soup.find_all('a',recursive=False)  #只对子节点

》》
    [<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>]
    []

4.1.4、 string

对标签中间的字符串域<>…<>进行检索,检索时精确输入,不精确输入时使用正则表达式。

print(soup.find_all(string = re.compile('pyth')))  #正则模糊检索,返回猎豹
 》》
	 ['This is a python demo page', 'The demo python introduces several python courses.']

4.2 其他常用方法

参数属性和find_all() 一致。
注意使用的时候是和标签相关的。
在这里插入图片描述
使用时应该是具体的哪个标签,再去找它的子孙辈或者先辈:

print(soup.a.find_parent('p'))
print('****')
print(soup.a.find_parents('p'))

如果直接是soup.find:

 print(soup.find_parent('a'))

因为soup是顶级,可能返回的都是NONE 或者空 [ ]

参考嵩天老师课程:http://www.icourse163.org/course/BIT-1001870001

猜你喜欢

转载自blog.csdn.net/dzg_chat/article/details/83959202