爬虫入门二 beautifulsoup

embedded/2024/12/31 7:15:28/

beautifulsoup简介">1 beautifulsoup简介

BeautifulSoup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过转换器实现文档导航、查找、修改。
pip install beautifulsoup4
http://beautifulsoup.readthedocs.io/zh_CN/latest/

2 前端知识

w3school 在线教程

HTTP:HyperText Markup Language 超文本标记语言
CSS:Cascading Style Sheets 层叠样式表
JAVASCRIPT:一种脚本语言,其源代码在发往客户端运行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释运行
XML:Extensible Markup Language可扩展标记语言

XML是被设计用来描述数据的,HTML是被设计用来显示数据的。与HTML相比,XML支持动态更新,标准性更强

beautifulsoup解析器">3 beautifulsoup解析器

比如BeautifulSoup(demo, 'html.parser') 中的html.parser

bf解析器.PNG

4 html结构

<></>构成所属关系。树形结构。下行,上行,平行遍历。

html基本结构.PNG

beautifulsoup解析html">5 使用beautifulsoup解析HTML

注意B和S大写,Python对大小写敏感

from bs4 import BeautifulSoup
import requestsdef html():# 得到未解析的HTML网页内容r = requests.get("https://whu.edu.cn/coremail/common/index_cm40.jsp")print(r.text)# 得到解析的HTML网页内容demo = r.textsoup = BeautifulSoup(demo, 'html.parser')print(soup.prettify())

beautifulsoup-类的基本元素与操作">6 BeautifulSoup 类的基本元素与操作

Tag,标签<></>开始结束
name,标签名,

的name是p。.name
attributes,标签属性(字典形式组织)。.attr
navigablestring,标签内非属性字符串..string
comment,标签内字符串的注释部分

下面是例子:
可以看到,web中有很多a标签,,而这里只返回了第一个

from bs4 import BeautifulSoup
import requestsdef html():# 得到未解析的HTML网页内容r = requests.get("https://whu.edu.cn/coremail/common/index_cm40.jsp")print(r.text)# 得到解析的HTML网页内容demo = r.textsoup = BeautifulSoup(demo, 'html.parser')#print(soup.prettify())print(soup.title)print(soup.a)#<title>武汉大学邮件系统</title>
#<a class="MTLinks">设为首页</a>

HTML中a锚文本A超链接标签格式: 被链接内容

beautifulsoup标签操作">6.1 BeautifulSoup标签操作

#查看标签a的属性
tag=soup.a
tag.attrs#查看标签a的属性中class的值
tag.attrs['class']#查看标签a的属性 的类型
type(tag.attrs)#查看标签a的非属性字符串
soup.a.string#查看标签a的非属性字符串属性 的类型
type(tag.a.string)#返回值为bs4.element.NavigableString  (可以遍历的字符串)
from bs4 import BeautifulSoup
import requestsdef html():# 得到未解析的HTML网页内容r = requests.get("https://whu.edu.cn/coremail/common/index_cm40.jsp")print(r.text)# 得到解析的HTML网页内容demo = r.textsoup = BeautifulSoup(demo, 'html.parser')#print(soup.prettify())print(soup.title)print(soup.a)# 查看标签a的属性tag = soup.aprint(tag.attrs)# 查看标签a的属性中class的值tag.attrs['class']# 查看标签a的属性 的类型print(type(tag.attrs))# 查看标签a的非属性字符串print(tag.string)# 查看标签a的非属性字符串属性 的类型print(type(tag.string))# 返回值为bs4.element.NavigableString  (可以遍历的字符串)

7 html遍历

上行,下行,平行。

html的遍历.PNG

7.1 标签树下行遍历 .content .children .descendants

7.1.1 .content

.contents 子节点的列表,将所有儿子节点存入列表

soup.body.contents#获得孩子节点的个数
len(soup.body.contents)
#分别输出各个子节点
soup.body.contents[0]
soup.body.contents[2]
#标号 由0开始

7.1.2 .children/.descendants

.contents 和 .children 属性仅包含tag的直接子节点,.descendants 属性可以对所有tag的子孙节点进行递归循环
需要遍历获取其中的内容。

for child in soup.body.children:print(child)
for child in soup.body.descendants:print(child)
def htmlergodic():# 得到未解析的HTML网页内容r = requests.get("https://whu.edu.cn/coremail/common/index_cm40.jsp")#print(r.text)# 得到解析的HTML网页内容demo = r.textsoup = BeautifulSoup(demo, 'html.parser')# 子节点的列表,将<tag>所有儿子节点存入列表#print(soup.body.contents)# 获得孩子节点的个数print(len(soup.body.contents))# 分别输出各个子节点print(soup.body.contents[0])print(soup.body.contents[2])# 标号 由0开始for child in soup.body.children:print(child)for child in soup.body.descendants:print(child)

7.2 标签树上行遍历 .parent/.parents

# a的父节点
soup.a.parent.name# 遍历
for parent in soup.a.parents:   #注意 sprint(parent.name)

7.3 标签树平行遍历 next_sibling/Previous_sibling

#获得a节点的上一个节点和下一个节点
soup.a.next_sibling
soup.a.previous_siblingfor sibling in soup.a.next_siblings: #注意sprint(sibling)

8 bs4的库的prettify()方法

BeautifulSoup 是bs4库的类,prettify()是方法。
.prettify()为HTML文本<>及其内容增加换行符
可以用于整个HTML文本,也可以用于单个标签
方法:
.prettify()

bs4库将任何HTML输入都变成utf‐8编码Python 3.x默认支持编码是utf‐8,解析无障碍

print(soup.body.prettify())

beautifulsoup信息检索--注意find标签名要加表示字符串">9 BeautifulSoup信息检索 注意find标签名要加''表示字符串

9.1 .find_all() 搜索并返回全部结果

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

def jiansuo():r = requests.get("http://www.baidu.com/")r.encoding = r.apparent_encodingdemo = r.textsoup = BeautifulSoup(demo, 'html.parser')print(soup.find_all('a'))

9.2 参数

name: 对标签名称的检索字符串
attrs: 对标签属性值的检索字符串,可标注属性检索
recursive: 是否对子孙全部检索,默认True
string: <>…</>中字符串区域的检索字符串

#搜索 class=“mnav” 的全部a标签
print(soup.find_all('a','mnav'))
# 搜索字符串为新闻的全部标签
print(soup.find_all(string='新闻'))

如果要部分匹配,则需要导入正则表达式库

9.3 扩展方法

<>.find()
<>.find_parents()
<>.find_parent()
<>.find_next_sibling()
<>.find_next_siblings()
<>.find_previous_sibling()
<>.find_previous_siblings()

bs4find扩展方法.PNG

10 实例

10.1 爬取武汉大学官方网站,含'樱'的新闻链接标题

导入requests库、BeautifulSoup类、re库
使用for循环,查找条件string=re.compile('樱'))
搜索类型为新闻链接,因此类型为‘a’
输出满足条件的tag的字符串

import re
import requests
from bs4 import BeautifulSoup
def sakura():r = requests.get("http://www.whu.edu.cn/")r.encoding = r.apparent_encodingdemo = r.textsoup = BeautifulSoup(demo,'html.parser')for tag in soup.find_all('a', string=re.compile('樱')):print(tag.string)

10.2 爬取 百度互联网热门人物排行

访问百度搜索风云榜 
人物--互联网人物
百度热搜

右键点击 “马云”--检查,查看对应的HTML代码

<a class="list-title" target="_blank" href="http://www.baidu.com/baidu?cl=3&amp;tn=SE_baiduhomet8_jmjb7mjw&amp;rsv_dl=fyb_top&amp;fr=top1000&amp;wd=%C2%ED%D4%C6" href_top="./detail?b=257&amp;c=9&amp;w=%C2%ED%D4%C6">马云</a>

分析可知人物连接标签名为a,class为list-title
使用soup.find_all(‘a’, ‘list-title’ ) 输出class为list-title
的a标签的字符串,即可书序得到排行榜的人物名单。
同时在前面加上他们索引序号index(tag.string)+1
即可得到今日互联网人物排行榜

def fyrw():r=requests.get("http://top.baidu.com/buzz?b=257&fr=topboards")r.encoding=r.apparent_encodingdemo=r.textsoup=BeautifulSoup(demo, 'html.parser')ulist = []for tag in soup.find_all('a', 'list-title' ):ulist.append(tag.string)print(ulist.index(tag.string)+1,ulist[ulist.index(tag.string)])

10.3 爬取 中国大学排行榜2016

从网络上获取大学排名网页内容
getHTMLText()
提取网页内容中信息到合适的数据结构
fillUnivList()
利用数据结构展示并输出结果
printUnivList()
http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html
检查网页代码看到结构是

<tbody><tr><td> 排位<td> 大学名...<tr>...    

这样就遍历标签的每个标签,提取前三个标签的string保存即可

def getHTMLText(url):try:r = requests.get(url, timeout=30)r.raise_for_status()r.encoding = r.apparent_encodingreturn r.textexcept:return ""def fillUnivList(ulist, html):soup = BeautifulSoup(html, "html.parser")for tr in soup.find('tbody').children: #提取tbody的每个tr标签if isinstance(tr,bs4.element.Tag): #判断tr是否是tag类型tds = tr('td')                 #tds[0] <td>1</td>.简写,等价于下一行代码#tds = tr.find_all('td')# ,然后用.string取stringulist.append([tds[0].string, tds[1].string, tds[3].string])def printUnivList(ulist, num):print("{:^10}\t{:^6}\t{:^10}".format("排名", "学校名称", "总分"))for i in range(num):u = ulist[i]print("{:^10}\t{:^6}\t{:^10}".format(u[0], u[1], u[2]))def main():uinfo = []url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html'html = getHTMLText(url)fillUnivList(uinfo, html)printUnivList(uinfo, 20)  # 20 univs

上面的问题是并没有对齐。
原因是当中文字符宽度不够时,采用西文字符填充;中西文字符占用宽度不同。
解决是采用中文字符的空格填充chr(12288)

def printUnivList(ulist, num):tplt = "{0:^4}\t{1:{3}^12}\t{2:^10}"print(tplt.format("排名", "学校名称", "总分", chr(12288)))for i in range(num):u = ulist[i]print(tplt.format(u[0], u[1], u[2], chr(12288)))

tplt为定义的输出格式模板变量,^代表居中,4/12/10代表输出宽度(当输出数据超过该数字时,以实际输出为准),
{3}代表打印输出时,我们使用format中的第3个变量(由0起始),也就是 chr(12288)
chr(12288)代表全角Unicode空格(即中文空格)

# :是引导符号
#  : <填充><对齐><宽度>,<精度><类型>  这里的 ','是千位分隔符
# 拿上面的代码举例
#tply:0,1,2对应输出的第0,1,2个数据。^表示居中,然后第0个数据宽4.中间{3}表示填充用format第3个变量也就是chr(12288)

10.4 最好大学2017.遇坑

同样的代码爬
http://www.zuihaodaxue.cn/zuihaodaxuepaiming2017.html
报错
TypeError: unsupported format string passed to NoneType.format

#2016
<tr class="alt"><td>1</td><td><div align="left">清华大学</div></td>#2017<tr class="alt"><td>1<td><div align="left">清华大学</div></

注意这里有坑,chrome检查,在console看到是没区别的(2017也是1)

检查页面源代码发现和2016比不同之处在于子节点“1”所对应的地方并非是一个完整的子节点,“1”并没有被一对完整的标签所包围,所以tds[0]实际上是被第一个标签所包围的所有内容,而这相当于把后续所有内容全给装进去了。
由于字符1仍是第一的标签下的第一个子节点,通过bs4库的contents方法来获得这个排名,由于是第一个子节点,tds[0].contents[0]就排名。
重新修改的代码如下

def fillUnivList(ulist, html):soup = BeautifulSoup(html, "html.parser")for tr in soup.find('tbody').children: #提取tbody的每个tr标签if isinstance(tr,bs4.element.Tag): #判断tr是否是tag类型tds = tr('td')                 #tds[0] <td>1</td>.简写,等价于下一行代码#tds = tr.find_all('td')# ,然后用.string取stringulist.append([tds[0].contents[0].string, tds[1].string, tds[3].string])

10.5 2016世界大学排名,遇坑

http://www.zuihaodaxue.cn/ARWU2016.html

先用了2016中国排名的方法,然后报错,然后看源码,没看出来不同。
就把爬的内容打印一下
发现大学名字打印的是none
然后对比2016中国和2016大学.

<td class="align-left"><a href="World-University-Rankings/Harvard-University.html" target="_blank">哈佛大学</a></td><td><div align="left">清华大学</div></td>

不明白就去查,
BeautifulSoup获取字符串为None_用beautifulsoup解析html获取文本为none-CSDN博客
用 .string 属性来提取标签里的内容时,该标签应该是只有单个节点的。比如上面的 1 标签那样。也就是说世界大学的标签影响了
那就直接提取.string就行了

def fillUnivList(ulist, html):soup = BeautifulSoup(html, "html.parser")for tr in soup.find('tbody').children: #提取tbody的每个tr标签if isinstance(tr,bs4.element.Tag): #判断tr是否是tag类型tds = tr('td')                 #tds[0] <td>1</td>.简写,等价于下一行代码#tds = tr.find_all('td')# ,然后用.string取stringtmp=tds[1].find('a')#print(tds[0].string, tmp.string, tds[3].string)ulist.append([tds[0].string, tmp.string, tds[3].string])

11 相关网站

0.北理工课程
视频去哪了呢?_哔哩哔哩_bilibili

1.廖雪峰官方网站
首页 - 廖雪峰的官方网站

2.Python 知识库
http://lib.csdn.net/python/node/68

  1. Python网络爬虫与信息提取(MOOC)
    Python网络爬虫与信息提取_北京理工大学_中国大学MOOC(慕课)

4.W3School 网页前端学习及在线编辑
HTML 系列教程

5.BeautifulSoup 官方文档
Beautiful Soup 4.12.0 文档 — Beautiful Soup 4.12.0 documentation


http://www.ppmy.cn/embedded/149743.html

相关文章

互联网路由架构

大家觉得有意义和帮助记得及时关注和点赞!!! 本书致力于解决实际问题&#xff0c;书中包含大量的架构图、拓扑图和真实场景示例&#xff0c;内容全面 且易于上手&#xff0c;是不可多得的良心之作。本书目的是使读者成为将自有网络集成到全球互联网 领域的专家。 以下是笔记内…

基于JAVA+SpringBoot+Vue的影院订票系统

基于JAVASpringBootVue的影院订票系统 前言 ✌全网粉丝20W,csdn特邀作者、博客专家、CSDN[新星计划]导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末附源码下载链接&#x1f345; 哈喽兄…

【HarmonyOS之旅】ArkTS语法(二)->动态构建UI元素

目录 1 -> Builder 2 -> BuilderParam8 2.1 -> 引入动机 2.2 -> 参数初始化组件 2.3 -> 尾随闭包初始化组件 3 -> Styles 4 -> Extend 5 -> CustomDialog 1 -> Builder 可通过Builder装饰器进行描述&#xff0c;该装饰器可以修饰一个函数&…

网络技术-QoS技术在网络中的位置

QoS技术包括流分类、流量监管、流量整形、限速、拥塞管理、拥塞避免等。下面对常用的技术进行简单地介绍。 如图&#xff0c;常用QoS技术在网络中的位置 如上图所示&#xff0c;流分类、流量监管、流量整形、拥塞管理和拥塞避免主要完成如下功能&#xff1a; 流分类&#xf…

Configfs - 用户空间驱动的内核对象配置

什么是configfs configfs 是一个基于 RAM 的文件系统&#xff0c;提供与 sysfs 相反的功能。sysfs 是一个基于文件系统的内核对象视图&#xff0c;而 configfs 是一个基于文件系统的内核对象管理器&#xff0c;即 config_items。 使用 sysfs&#xff0c;可以在内核中创建一个…

使用 VSCode 学习与实践 LaTeX:从插件安装到排版技巧

文章目录 背景介绍编辑器编译文件指定输出文件夹 usepackagelatex 语法列表插入图片添加参考文献 背景介绍 最近在写文章&#xff0c;更喜欢latex的论文引用。然后开始学习 latex。 编辑器 本文选择vscode作为编辑器&#xff0c;当然大家也可以尝试overleaf。 overleaf 有网…

SPI实验 LED数码管

LED数码管&#xff08;LED Segment Displays&#xff09;是由8个发光二极管构成&#xff0c;并按照一定的图形及排列封装在一起的显示器件。其中7个LED构成7笔字形&#xff0c;1个LED构成小数点&#xff08;固有时成为八段数码管&#xff09;。 LED数码管有两大类&#xff0c;…

【国产NI替代】基于全国产FPGA的16振动+2转速+8路IO口输入输出(24bits)256k采样率,高精度终端采集板卡

16振动2转速8路IO口输入输出&#xff08;24bits&#xff09; 高精度终端采集板卡 采用AG16KF256国产FPGA的硬件架构&#xff0c;外扩 16MB的SDRAM做为千兆网的发送缓存&#xff0c;比起同 款带ARM的硬件架构&#xff0c;纯FPGA的架构虽然边缘 计算能力不如ARM&#xff0c;但…