爬虫笔记2-解析

BeautifulSoup 用于解析已经抓取的文件内容。是解析、遍历、维护“标签树”的功能库。

pip install beautifulsoup4 命令安装模块,import bs4 导入该模块。

BeautifulSoup 库将任何 HTML 输入都变成 utf‐8 编码,Python 3 默认支持编码 utf‐8。

BeautifulSoup 对象

可以对应到文档的标签树。

解析远程网页:

import requests, bs4

res = requests.get('https://www.baidu.com/')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, features="html.parser")
print(type(soup)) # <class 'bs4.BeautifulSoup'>
print(soup.prettify()) # 输出 HTML 文档内容 

解析本地文件:

from bs4 import BeautifulSoup

file = open('/Users/silas/Downloads/GDT DEV guide.4.16.html')
soup = BeautifulSoup(file, "html.parser")
print(type(soup))  # <class 'bs4.BeautifulSoup'>

解析器

解析器

使用方法

条件

bs4 的 HTML 解析器

BeautifulSoup(mk,'html.parser')

安装 bs4 库

lxml 的 HTML 解析器

BeautifulSoup(mk,'lxml')

pip install lxml

lxml 的 XML 解析器

BeautifulSoup(mk,'xml')

pip install lxml

html5lib 的解析器

BeautifulSoup(mk,'html5lib')

pip install html5lib

标签元素

select 方法寻找元素:

soup.select('div')  # 在 div 的标签元素
soup.select('#author')  # 属性 id 为 author 的元素
soup.select('div #author')  # 规则可以组合。在 div 里,且属性 id 为 author 的元素
soup.select('.notice')  # 属性 class 为 notice 的元素
soup.select('div span')  # 所有在 div 内的 span 内的元素
soup.select('div > span')  # 所有直接在 div 内的 span 内的元素
soup.select('input[name]')  # 在 input 里且有属性 name 的元素
soup.select('input[type="button]')  # 在 input 里且有属性 type,且属性值为 button 的元素

select() 方法返回一个 Tag 对象的列表,这是 BeautifulSoup 表示一个 HTML 元素的方式。

  • Tag 值可以传递给 str() 函数,显示它们代表的 HTML 标签。
  • Tag 值调用 getText() 方法获取标签里的内容。
  • Tag 值的 get() 方法传入属性名作为参数,获取其属性的值。
>>> tags = soup.select('input[name]')
 
>>> len(tags) # 列表长度
 
3
>>> type(tags[0])
 
<class 'bs4.element.Tag'>
>>> str(tags[0])
 
'<input class="search_key" id="cbsearchtxt" name="q" onkeypress="if(event.keyCode==13){document.getElementById(\'cbsearchsub\').click();return false;}" size="30" type="text"/>'
>>> tags[0].getText() # 自闭合,没有内容
 
''

也可以通过标签名直接获取 Tag,然后获取里面的内容。

tag = soup.p # 获取 p 标签
tag.name # 标签名
tag.attrs # 属性字典
tag.string # 标签内容

基本元素

说明

Tag

标签,最基本的信息组织单元,分别用 <>和 </> 标明开头和结尾

Name

标签的名字, <p>…</p> 的名字是 p,格式:<tag>.name

Attributes

标签的属性,字典形式组织,格式:<tag>.attrs

NavigableString

标签内非属性字符串,<>…</> 中字符串,格式:<tag>.string

Comment

标签内字符串的注释部分,一种特殊的 Comment 类型

>>> import requests
>>> from bs4 import BeautifulSoup
>>> res = requests.get('https://www.baidu.com/')
>>> res.status_code
200
>>> res.encoding = res.apparent_encoding
>>> soup = BeautifulSoup(res.text, 'html.parser')
>>> soup.title
<title>百度一下,你就知道</title>
  1. Tag 寻找 <a> 标签,是第一个 >>> tag = soup.a >>> tag <a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
  2. Name >>> tag.name 'a' >>> tag.parent.name 'div'
  3. Attributes >>> tag.attrs # 字典类型 {'href': 'http://news.baidu.com', 'name': 'tj_trnews', 'class': ['mnav']} >>> tag.attrs['class'] ['mnav']
  4. NavigableString >>> tag.string '新闻' >>> type(tag.string) <class 'bs4.element.NavigableString'>
  5. Comment >>> newSoup = BeautifulSoup("<b><!-- This is a comment --></b><p>This is not a comment</p>", "html.parser") >>> newSoup.b.string ' This is a comment ' >>> type(newSoup.b.string) # 同样的方法获取,区别是类型不同 <class 'bs4.element.Comment'> >>> newSoup.p.string 'This is not a comment' >>> type(newSoup.p.string) <class 'bs4.element.NavigableString'>

标签树的遍历

下行遍历

属性

说明

.contents

子节点的列表, 将 <tag> 所有子节点存入列表

.children

子节点的迭代类型, 与 .contents 类似,用于循环遍历子节点

.descendants

子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

>>> soup.head
<head><meta content="text/html;charset=utf-8" http-equiv="content-type"/><meta content="IE=Edge" http-equiv="X-UA-Compatible"/><meta content="always" name="referrer"/><link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/><title>百度一下,你就知道</title></head>

>>> soup.head.contents # 子标签存入列表
[<meta content="text/html;charset=utf-8" http-equiv="content-type"/>, <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>, <meta content="always" name="referrer"/>, <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>, <title>百度一下,你就知道</title>]
>>> soup.head.contents[2]
<meta content="always" name="referrer"/>

>>> for child in soup.head.children:
    print(child) # 子节点

    
<meta content="text/html;charset=utf-8" http-equiv="content-type"/>
<meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
<meta content="always" name="referrer"/>
<link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
<title>百度一下,你就知道</title>

>>> for child in soup.head.descendants:
    print(child) # 一层一层的递归迭代

    
<meta content="text/html;charset=utf-8" http-equiv="content-type"/>
<meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
<meta content="always" name="referrer"/>
<link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
<title>百度一下,你就知道</title>
百度一下,你就知道

上行遍历

属性

说明

.parent

节点的父亲标签

.parents

节点先辈标签的迭代类型,用于循环遍历先辈节点

>>> soup.title.parent
<head><meta content="text/html;charset=utf-8" http-equiv="content-type"/><meta content="IE=Edge" http-equiv="X-UA-Compatible"/><meta content="always" name="referrer"/><link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/><title>百度一下,你就知道</title></head>
>>> soup.parent # soup 本身没有父标签

迭代所有父标签

>>> for parent in soup.a.parents:
    if parent is None: # 最后会迭代 soup 本身,它没有 parent
        print(parent)
    else:
        print(parent.name)

        
div
div
div
div
body
html
[document]

平行遍历

属性

说明

.next_sibling

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

.previous_sibling

返回按照 HTML 文本顺序的上一个平行节点标签

.next_siblings

迭代类型, 返回按照 HTML 文本顺序的后续所有平行节点标签

.previous_siblings

迭代类型, 返回按照HTML文本顺序的前续所有平行节点标签

平行遍历发生在同一个父节点下的各节点下。可能是 NavigableString 类型,不一定还是一个标签

>>> soup.a.next_sibling
' '
>>> soup.a.next_sibling.next_sibling
<a class="mnav" href="https://www.hao123.com" name="tj_trhao123">hao123</a>
>>> soup.a.previous_sibling
' '
>>> soup.a.previous_sibling.previous_sibling # 前面没有了,什么都不输出
# 遍历后续节点
for sibling in soup.a.next_siblings:
    print(sibling)
    
# 遍历前续节点
for sibling in soup.a.previous_siblings:
    print(sibling)

格式化输出 HTML 内容

prettify() 方法为 HTML 文本标签及其内容增加 \n

>>> soup.prettify()
'<!DOCTYPE html>\n<!--STATUS OK-->\n<html>\n <head>\n  <meta content="text/html;charset=utf-8" http-equiv="content-type"/>\n  <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>\n  <meta content="always" name="referrer"/>\n  <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>\n  <title>\n   百度一下,你就知道\n  </title>\n </head>\n <body link="#0000cc">\n  <div id="wrapper">\n
...

>>> print(soup.prettify())
<!DOCTYPE html>
<!--STATUS OK-->
<html>
 <head>
  <meta content="text/html;charset=utf-8" http-equiv="content-type"/>
  <meta content="IE=Edge" http-equiv="X-UA-Compatible"/>
  <meta content="always" name="referrer"/>
  <link href="https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css" rel="stylesheet" type="text/css"/>
  <title>
   百度一下,你就知道
  </title>
 </head>
 <body link="#0000cc">
  <div id="wrapper">
   <div id="head">
    <div class="head_wrapper">
     <div class="s_form">
...

prettify() 也可用于标签

>>> print(soup.a.prettify())
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">
 新闻
</a>

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • java开发之Java 的 Filter 过滤器学习

    Filter也称之为过滤器,它是Servlet技术中最实用的技术,WEB开发人员通过Filter技术,对web服务器管理的所有web资源:例如Jsp, Serv...

    用户1289394
  • Vue的Computed的使用

    Dream城堡
  • TCGA体细胞突变系列教程--胃癌

    有这个想法很久了,我教了很多人如何批量下载TCGA数据,以及分析各个癌症的somatic突变信息以及TMB,还有突变的特征频谱。

    生信技能树
  • Vue的watch监听事件

    Dream城堡
  • 如何爬取王者荣耀英雄皮肤高清图片?

    临下班前,看到群里有人在讨论用王者农药的一些皮肤作为电脑的壁纸,什么高清的,什么像素稍低的,网上查了一手,也有,但像素都不一样,所以,我就想着,自己去官网直接爬...

    我就是马云飞
  • 常用正则表达式(高亮,markdown) 原

    1.oscer 们会喜欢用 Markdown 编辑器吗:https://www.oschina.net/question/12_75077

    晓歌
  • Spark2.4.0发布了!

    http://spark.apache.org/releases/spark-release-2-4-0.html

    Spark学习技巧
  • 通用的layui框架系统管理后台模板

    公司又要开始做新的项目了,这次的项目又是后台管理系统,老板说,之前的后台管理系统都是差不多的,这一次我们换个框架吧,然后抄了一下竞争公司的模板,给我发来了一张原...

    祈澈菇凉
  • “骇极杯”全国大学生网络安全邀请赛WriteUp

    这里看到需要伪造ip 在头中伪造ip只有几种情况:xff xci clientip remoteaddr

    安恒网络空间安全讲武堂
  • Spring mvc中统一对ResponseBody进行封装

    在一个前后端分离的项目中,需要对后端RestController里返回的ResponseBody进行统一的封装,让所有的API结果的都是json对象,带有是否成...

    大神带我来搬砖

扫码关注云+社区

领取腾讯云代金券