3.bs4包学习(html源码解析)

上一篇博客2.urllib库学习、反爬虫网页源码爬取介绍了如何爬取网页源码,这一篇博客介绍如何对爬取到的html文件进行解析

使用 Beautiful Soup 解析 html 文件

1.先爬取到百度首页网页源码保存到本地

import pickle  # 保存html文件
import urllib.request
url = "http://www.baidu.com"
response = urllib.request.urlopen(url)
pickle.dump(response.read(),open('./baidu.html','wb'))

如果有一天,baidu不再是那个百度,本博客可以下载以下html源码进行后续教程的学习
2021.02.02.12:57爬取baidu首页源码:https://wwx.lanzoui.com/i5QOvl7peyb

2.使用html.parser进行解析

from bs4 import BeautifulSoup
file = open("./baidu.html", "rb")
html = file.read()  # 读取文本
bs = BeautifulSoup(html, "html.parser")  # bs对象来解析,使用html.parser解析器

bs是创建的一个BeautifulSoup解析对象,bs是<class ‘bs4.BeautifulSoup’>类型,BeautifulSoup4将复杂HTML文档转换为一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

  • 1.Tag

  • 2.NavigableString

  • 3.BeautifulSoup

  • 4.Comment


1. tag:标签(包含标签内的内容),只能拿到所找到的第一个匹配的标签
print(bs.title)
print(type(bs.title))

bs.title匹配第一个title是:百度一下,你就知道

type(bs.title)是:<class ‘bs4.element.Tag’>

解析对象.标签,得到的是标签及其内容

2. NavigableString:标签里的内容
print(bs.title.string)
print(type(bs.title.string))  # NavigableString

bs.title匹配第一个title是:百度一下,你就知道

扫描二维码关注公众号,回复: 12501490 查看本文章

bs.title.string就是:百度一下,你就知道

type(bs.title.string)是:<class ‘bs4.element.NavigableString’>

解析对象.标签.string是标签的中间的内容

除了获取标签及其内容、获取标签的内容、还可以获取标签的属性attributes:
print(bs.a)
print(bs.a.attrs)
print(type(bs.a.attrs))  # <class 'dict'>

bs.a是:百度首页

bs.a.attrs是:{‘class’: [‘toindex’], ‘href’: ‘/’}

type(bs.a.attrs)是:<class ‘dict’>

解析对象.标签.attrs是标签的所有属性(attrs可以打印a标签的class、href和name等),返回包含所有属性键值对的字典。

3. BeautifulSoup:表示整个文档
print(bs)  # 打印的就是整个文档
print(type(bs))
print(bs.name)  # [document]
print(bs.a.name)

print(bs) 打印的就是整个html文档内容

type(bs)是:<class ‘bs4.BeautifulSoup’>

bs.name是:[document]

bs.a.name是:a

解析对象.标签.name是标签的类型,或者解析对象.name是解析对象的类型

5.Comment:是一个特殊的NavigableString,输出的内容不包含注释

要看到Comment,请手动将baidu.html中百度首页修改成

在这里插入图片描述

注意:再次执行时请频闭爬取并保存baidu.html部分的代码

print(bs.a)
print(bs.a.string)
print(type(bs.a.string))  # Comment

bs.a是:

bs.a.string是:百度首页

type(bs.a.string)是:<class ‘bs4.element.Comment’>

发现解析对象.标签.string只要标签中的内容带注释,那么注释便会自动屏蔽掉。并且解析对象.标签.string变成了<class ‘bs4.element.Comment’>类型,简单总结Comment是BeautifulSoup的一种特殊情况


实战应用

解析器将html源码,组织管理成树状数据结构的内容,对于所有节点的获取采用遍历的方式

节点获取:遍历

print(bs.head.contents)
print(bs.head.contents[1])

bs.head.contents是head标签中的所有一级标签

bs.head.contents[1]拿到head标签中的所有一级标签中的第二个

析对象.head.contents拿到了head标签中的所有一级标签,采用列表返回

文档的搜索:针对性(指定div)

1.find_all

字符串过滤,匹配与字符串完全匹配的所有标签内容,返回结果列表,举个栗子:

t_list = bs.find_all("a")
print(t_list)

查找所有的a标签,返回结果列表

2.正则表达式搜索:使用search方法来匹配内容

还是上面的栗子,查找所有的带a字符的内容

t_list = bs.find_all(re.compile("a")) 
printf(t_list)
t_list = bs.find_all(text=re.compile("\d"))  # 包含数字的字符串
for it in t_list:
    print(it)

re.compile(“a”)创建了一个匿名模式对象,查找的是标签及内容。正则表达式的模式对象也可以赋值给text,text=re.compile("\d"),查找的是含数字的内容(不包含标签本身)

3.方法:传入一个函数(方法),根据函数的要求来搜索

首先定义一个函数,返回标签是否有name属性的真值1

def name_is_exists(tag):
    return tag.has_attr("name")

t_list = bs.find_all(name_is_exists)  # 查询所有有name属性的标签
    print(t_list)

bs.find_all(name_is_exists)查找所有带name属性的标签

4.kwargs 参数
t_list = bs.find_all(id="head")  # id是head的标签
print(it)
t_list = bs.find_all(class_=True)  # 有class属性值的标签
print(it)
t_list = bs.find_all(href="http://news.baidu.com")  # 查找href="http://news.baidu.com"
print(it)
5.text参数: 特定文本

查找含"hao123"文本的内容

t_list = bs.find_all(text="hao123")
# 参数可以是列表,结果是并集
t_list = bs.find_all(text=["hao123","地图","贴吧"])
for it in t_list:
    print(it)

可以同时匹配多个文本内容

6.limit参数:得到前limit个匹配元素
t_list = bs.find_all("a", limit=3)
for it in t_list:
    print(it)

上述例子得到了前三个a标签

7.CSS选择器:页面中的嵌套,通过id或者class快速定位,参数可以是标签id和class—用法类似于jQuery
    # 按标签查找,返回所有匹配的标签
    print(bs.select('title'))
    # 按类名查找,返回所有匹配的标签
    print(bs.select('.mnav'))
    # 按id查找,返回所有匹配的标签
    print(bs.select('#u1'))
    # 筛选某个标签的属性或者id等于什么,返回所有匹配的标签
    print(bs.select("a[class='s-set-hotsearch set-show']"))  # 筛选class是's-set-hotsearch set-show'的a标签
    # 通过层级结构查找子标签
    res = bs.select("head > link")# 查找head标签中的所有link子标签,不包含孙标签
    print(res)  
    print(len(res))
    for it in res:
        print(it)
    # 查找兄弟标签,特点是只能往后查找
    t_list = bs.select(".toindex ~ .pf")  # 先找到class是toindex的标签,然后向后查找class是pf的同级标签
    print(len(t_list))
    print(t_list[0].get_text())
    这个例子涉及到html源码中的如下内容
    """
		<a class="toindex" href="/">百度首页</a>
		<a href="javascript:;" name="tj_settingicon" class="pf">设置<i class="c-icon c-icon-triangle-down"></i></a>
		<a href="https://passport.baidu.com/v2/?login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2F&sms=5" name="tj_login" class="lb" onclick="return false;">登录</a>
		<div class="bdpfmenu"></div>
    """

任务驱动型开发:将豆瓣Top250电影爬取的数据组织成树形结构数据

# import bs4 #只需要使用bs4中的BeautifulSoup因此可以如下写法:
from bs4 import BeautifulSoup  # 网页解析,获取数据
import urllib.request, urllib.error  # 指定url,获取网页数据


def main():
    # 爬取的网页
    baseurl = "https://movie.douban.com/top250?start="
    # # 保存的路径
    savepath = ".\\豆瓣电影Top250.xls"  # 使用\\表示层级目录或者在整个字符串前加r“.\豆瓣电影Top250”
    savepath2Db = "movies.db"
    # # 1.爬取网页
    # print(askURL(baseurl))
    datalist = getData(baseurl)
    print(datalist)



# 爬取网页
def getData(baseurl):
    datalist = []
    for i in range(0, 10):  # 一页25条电影
        url = baseurl + str(i*25)
        html = askURL(url)  # 保存获取到的网页源码
        # print(html)
        # 2.解析数据(逐一)
        soup = BeautifulSoup(html, "html.parser")  # 使用html.parser解析器解析html文档形成树形结构数据
        # 解析...
    return datalist


# 得到执行url的网页信息
def askURL(url):
    # 头部信息 其中用户代理用于伪装浏览器访问网页
    head = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
                          "Chrome/87.0.4280.88 Safari/537.36"}
    req = urllib.request.Request(url, headers=head)
    html = ""  # 获取到的网页源码
    try:
        response = urllib.request.urlopen(req)
        html = response.read().decode("utf-8")
    except urllib.error.URLError as e:
        if hasattr(e, "code"):  # has attribute
            print(e.code)
        if hasattr(e, "reason"):
            print(e.reason)
    return html


if __name__ == '__main__':
    main()

  1. 布尔 ↩︎

猜你喜欢

转载自blog.csdn.net/qq_43808700/article/details/113588874