python爬虫学习笔记之Beautifulsoup模块用法详解

本文实例讲述了python爬虫学习笔记之Beautifulsoup模块用法。分享给大家供大家参考,具体如下:

相关内容:

  • 什么是beautifulsoup
  • bs4的使用
    • 导入模块
    • 选择使用解析器
    • 使用标签名查找
    • 使用find\find_all查找
    • 使用select查找

首发时间:2018-03-02 00:10


什么是beautifulsoup:

  • 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档导航,查找,修改文档的方式.(官方)
  • beautifulsoup是一个解析器,可以特定的解析出内容,省去了我们编写正则表达式的麻烦。

Beautiful Soup 3 目前已经停止开发,我们推荐在现在的项目中使用Beautiful Soup 4

beautifulsoup的版本:最新版是bs4


bs4的使用:

1.导入模块:

from bs4 import beautifulsoup

2.选择解析器解析指定内容:

soup=beautifulsoup(解析内容,解析器)

常用解析器:html.parser,lxml,xml,html5lib

有时候需要安装安装解析器:比如pip3 install lxml

BeautifulSoup默认支持Python的标准HTML解析库,但是它也支持一些第三方的解析库:

解析器之间的区别 #此处摘自官方文档

Beautiful Soup为不同的解析器提供了相同的接口,但解析器本身时有区别的.同一篇文档被不同的解析器解析后可能会生成不同结构的树型文档.区别最大的是HTML解析器和XML解析器,看下面片段被解析成HTML结构:

BeautifulSoup("<a><b /></a>")
# <html><head></head><body><a><b></b></a></body></html>

因为空标签<b />不符合HTML标准,所以解析器把它解析成<b></b>

同样的文档使用XML解析如下(解析XML需要安装lxml库).注意,空标签<b />依然被保留,并且文档前添加了XML头,而不是被包含在<html>标签内:

BeautifulSoup("<a><b /></a>", "xml")
# <?xml version="1.0" encoding="utf-8"?>
# <a><b/></a>

HTML解析器之间也有区别,如果被解析的HTML文档是标准格式,那么解析器之间没有任何差别,只是解析速度不同,结果都会返回正确的文档树.

但是如果被解析文档不是标准格式,那么不同的解析器返回结果可能不同.下面例子中,使用lxml解析错误格式的文档,结果</p>标签被直接忽略掉了:

BeautifulSoup("<a></p>", "lxml")
# <html><body><a></a></body></html>

使用html5lib库解析相同文档会得到不同的结果:

BeautifulSoup("<a></p>", "html5lib")
# <html><head></head><body><a><p></p></a></body></html>

html5lib库没有忽略掉</p>标签,而是自动补全了标签,还给文档树添加了<head>标签.

使用pyhton内置库解析结果如下:

BeautifulSoup("<a></p>", "html.parser")
# <a></a>

与lxml [7] 库类似的,Python内置库忽略掉了</p>标签,与html5lib库不同的是标准库没有尝试创建符合标准的文档格式或将文档片段包含在<body>标签内,与lxml不同的是标准库甚至连<html>标签都没有尝试去添加.

因为文档片段“<a></p>”是错误格式,所以以上解析方式都能算作”正确”,html5lib库使用的是HTML5的部分标准,所以最接近”正确”.不过所有解析器的结构都能够被认为是”正常”的.

不同的解析器可能影响代码执行结果,如果在分发给别人的代码中使用了 BeautifulSoup ,那么最好注明使用了哪种解析器,以减少不必要的麻烦.

3.操作【约定soup是beautifulsoup(解析内容,解析器)返回的解析对象】:

  • 使用标签名查找

    • 使用标签名来获取结点:

      • soup.标签名
    • 使用标签名来获取结点标签名【这个重点是name,主要用于非标签名式筛选时,获取结果的标签名】:
      • soup.标签.name
    • 使用标签名来获取结点属性:
      • soup.标签.attrs【获取全部属性】
      • soup.标签.attrs[属性名]【获取指定属性】
      • soup.标签[属性名]【获取指定属性】
      • soup.标签.get(属性名)
    • 使用标签名来获取结点的文本内容:
      • soup.标签.text
      • soup.标签.string
      • soup.标签.get_text()

补充1:上面的筛选方式可以使用嵌套:

print(soup.p.a)#p标签下的a标签

补充2:以上的name,text,string,attrs等方法都可以使用在当结果是一个bs4.element.Tag对象的时候:

from bs4 import BeautifulSoup

html = """
<html >
<head>
  <meta charset="UTF-8">
  <title>this is a title</title>
</head>
<body>
<p class="news">123</p>
<p class="contents" id="i1">456</p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
</body>
</html>
"""

soup = BeautifulSoup(html,'lxml')

print("获取结点".center(50,'-'))
print(soup.head)#获取head标签
print(soup.p)#返回第一个p标签
#获取结点名
print("获取结点名".center(50,'-'))
print(soup.head.name)
print(soup.find(id='i1').name)
#获取文本内容
print("获取文本内容".center(50,'-'))
print(soup.title.string)#返回title的内容
print(soup.title.text)#返回title的内容
print(soup.title.get_text())
#获取属性
print("-----获取属性-----")
print(soup.p.attrs)#以字典形式返回标签的内容
print(soup.p.attrs['class'])#以列表形式返回标签的值
print(soup.p['class'])#以列表形式返回标签的值
print(soup.p.get('class'))

#############
t=soup.title
print(type(t))#<class 'bs4.element.Tag'>
print(t.name)#title
print(t.text)

#嵌套选择:
print(soup.head.title.string)
    • 获取子结点【直接获取也会获取到'\n',会认为'\n'也是一个标签】:

      • soup.标签.contents【返回值是一个列表】
      • soup.标签.children【返回值是一个可迭代对象,获取实际子结点需要迭代】
    • 获取子孙结点:
      • soup.标签.descendants【返回值也是一个可迭代对象,实际子结点需要迭代】
    • 获取父结点:
      • soup.标签.parent
    • 获取祖先结点[父结点,祖父结点,曾祖父结点…]:
      • soup.标签.parents【】
    • 获取兄弟结点:
      • soup.next_sibling【获取后面的一个兄弟结点】
      • soup.next_siblings【获取后面所有的兄弟结点】【返回值是一个可迭代对象】
      • soup.previous_sibling【获取前一兄弟结点】
      • soup.previous_siblings【获取前面所有的兄弟结点】【返回值是一个可迭代对象】

补充3:与补充2一样,上面的函数都可以使用在当结果是一个bs4.element.Tag对象的时候。

from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
  <a >78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
<span>aspan</span>
</body>
</html>
"""
soup = BeautifulSoup(html, 'lxml')

#获取子结点
print("获取子结点".center(50,'-'))
print(soup.p.contents)
print("\n")
c=soup.p.children#返回的是一个可迭代对象
for i,child in enumerate(c):
  print(i,child)

print("获取子孙结点".center(50,'-'))
print(soup.p.descendants)
c2=soup.p.descendants
for i,child in enumerate(c2):
  print(i,child)

print("获取父结点".center(50,'-'))
c3=soup.title.parent
print(c3)

print("获取父,祖先结点".center(50,'-'))
c4=soup.title.parents
print(c4)
for i,child in enumerate(c4):
  print(i,child)

print("获取兄弟结点".center(50,'-'))
print(soup.p.next_sibling)
print(soup.p.previous_sibling)
for i,child in enumerate(soup.p.next_siblings):
  print(i,child,end='\t')
for i,child in enumerate(soup.p.previous_siblings):
  print(i,child,end='\t')
  • 使用find\find_all方式:

    • find( name , attrs , recursive , text , **kwargs )【根据参数来找出对应的标签,但只返回第一个符合条件的结果】
    • find_all( name , attrs , recursive , text , **kwargs ):【根据参数来找出对应的标签,但只返回所有符合条件的结果】
    • 筛选条件参数介绍:
      • name:为标签名,根据标签名来筛选标签
      • attrs:为属性,,根据属性键值对来筛选标签,赋值方式可以为:属性名=值,attrs={属性名:值}【但由于class是python关键字,需要使用class_】
      • text:为文本内容,根据指定文本内容来筛选出标签,【单独使用text作为筛选条件,只会返回text,所以一般与其他条件配合使用】
      • recursive:指定筛选是否递归,当为False时,不会在子结点的后代结点中查找,只会查找子结点
    • 获取到结点后的结果是一个bs4.element.Tag对象,所以对于获取属性、文本内容、标签名等操作可以参考前面“使用标签筛选结果”时涉及的方法
from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
  <a id='i2'>78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
<span>aspan</span>
</body>
</html>
"""
soup = BeautifulSoup(html, 'lxml')

print("---------------------")
print(soup.find_all('a'),end='\n\n')
print(soup.find_all('a')[0])
print(soup.find_all(attrs={'id':'i1'}),end='\n\n')
print(soup.find_all(class_='news'),end='\n\n')
print(soup.find_all('a',text='123456'))#
print(soup.find_all(id='i2',recursive=False),end='\n\n')#
a=soup.find_all('a')
print(a[0].name)
print(a[0].text)
print(a[0].attrs)
  • 使用select筛选【select使用CSS选择规则】:

    • soup.select(‘标签名'),代表根据标签来筛选出指定标签
    • CSS中#xxx代表筛选id,soup.select(‘#xxx')代表根据id筛选出指定标签,返回值是一个列表
    • CSS中.###代表筛选class,soup.select('.xxx')代表根据class筛选出指定标签,返回值是一个列表
    • 嵌套select: soup.select(“#xxx .xxxx”),如(“#id2 .news”)就是id=”id2”标签下class=”news的标签,返回值是一个列表
    • 获取到结点后的结果是一个bs4.element.Tag对象,所以对于获取属性、文本内容、标签名等操作可以参考前面“使用标签筛选结果”时涉及的方法
from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
  <a id='i2'>78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
<span class="span1" id='i4'>aspan</span>
</body>
</html>
"""
soup = BeautifulSoup(html, 'lxml')
sp1=soup.select('span')#返回结果是一个列表,列表的元素是bs4元素标签对象

print(soup.select("#i2"),end='\n\n')
print(soup.select(".news"),end='\n\n')
print(soup.select(".news #i2"),end='\n\n')

print(type(sp1),type(sp1[0]))
print(sp1[0].name)#列表里面的元素才是bs4元素标签对象
print(sp1[0].attrs)
print(sp1[0]['class'])

补充4:

对于代码不齐全的情况下,可以使用soup.prettify()来自动补全,一般情况下建议使用,以避免代码不齐。

from bs4 import BeautifulSoup
html = """
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<p class="news"><a >123456</a>
  <a id='i2'>78910</a>
</p><p class="contents" id="i1"></p>
<a href="http://www.baidu.com" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >advertisements</a>
<span class="span1" id='i4'>aspan

</html>
"""
soup = BeautifulSoup(html, 'lxml')
c=soup.prettify()#上述html字符串中末尾缺少</span> 和 </body>
print(c)

如果想要获得更详细的介绍,可以参考官方文档,令人高兴的是,有了比较简易的中文版:

https://www.crummy.com/software/BeautifulSoup/bs4/doc/index.zh.html



更多关于Python相关内容可查看本站专题:《Python Socket编程技巧总结》、《Python正则表达式用法总结》、《Python数据结构与算法教程》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

希望本文所述对大家Python程序设计有所帮助。

(0)

相关推荐

  • python3 BeautifulSoup模块使用字典的方法抓取a标签内的数据示例

    本文实例讲述了python3 BeautifulSoup模块使用字典的方法抓取a标签内的数据.分享给大家供大家参考,具体如下: # -*- coding:utf-8 -*- #python 2.7 #XiaoDeng #http://tieba.baidu.com/p/2460150866 #标签操作 from bs4 import BeautifulSoup import urllib.request import re #如果是网址,可以用这个办法来读取网页 #html_doc = "htt

  • Python爬虫包BeautifulSoup实例(三)

    一步一步构建一个爬虫实例,抓取糗事百科的段子 先不用beautifulsoup包来进行解析 第一步,访问网址并抓取源码 # -*- coding: utf-8 -*- # @Author: HaonanWu # @Date: 2016-12-22 16:16:08 # @Last Modified by: HaonanWu # @Last Modified time: 2016-12-22 20:17:13 import urllib import urllib2 import re impor

  • Python爬虫包BeautifulSoup异常处理(二)

    面对网络不稳定,页面更新等问题,很可能出现程序异常的问题,所以我们要对程序进行一些异常处理.大家可能觉得处理异常是一个比较麻烦的活,但在面对复杂网页和任务的时候,无疑成为一个很好的代码习惯. 网页'404'.'500'等问题 try: html = urlopen('http://www.pmcaff.com/2221') except HTTPError as e: print(e) 返回的是空网页 if html is None: print('没有找到网页') 目标标签在网页中缺失 try

  • python爬虫入门教程--HTML文本的解析库BeautifulSoup(四)

    前言 python爬虫系列文章的第3篇介绍了网络请求库神器 Requests ,请求把数据返回来之后就要提取目标数据,不同的网站返回的内容通常有多种不同的格式,一种是 json 格式,这类数据对开发者来说最友好.另一种 XML 格式的,还有一种最常见格式的是 HTML 文档,今天就来讲讲如何从 HTML 中提取出感兴趣的数据 自己写个 HTML 解析器来解析吗?还是用正则表达式?这些都不是最好的办法,好在,Python 社区在这方便早就有了很成熟的方案,BeautifulSoup 就是这一类问题

  • python3第三方爬虫库BeautifulSoup4安装教程

    Python3安装第三方爬虫库BeautifulSoup4,供大家参考,具体内容如下 在做Python3爬虫练习时,从网上找到了一段代码如下: #使用第三方库BeautifulSoup,用于从html或xml中提取数据 from bs4 import BeautifulSoup 自己实践后,发现出现了错误,如下所示:    以上错误提示是说没有发现名为"bs4"的模块.即"bs4"模块未安装.    进入Python安装目录,以作者IDE为例,    控制台提示第三

  • Python爬虫库BeautifulSoup获取对象(标签)名,属性,内容,注释

    一.Tag(标签)对象 1.Tag对象与XML或HTML原生文档中的tag相同. from bs4 import BeautifulSoup soup = BeautifulSoup('<b class="boldest">Extremely bold</b>','lxml') tag = soup.b type(tag) bs4.element.Tag 2.Tag的Name属性 每个tag都有自己的名字,通过.name来获取 tag.name 'b' tag.

  • Python爬虫包BeautifulSoup简介与安装(一)

    先发官方文档的地址:官方文档 学习使用的书籍是Python网络数据采集(Ryan Mitchell著),大约是一些笔记的整理. Beautiful Soup的简介 简单来说,Beautiful Soup是python的一个库,最主要的功能是从网页抓取数据.官方解释如下: Beautiful Soup提供一些简单的.python式的函数用来处理导航.搜索.修改分析树等功能.它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序. Beauti

  • python利用beautifulSoup实现爬虫

    以前讲过利用phantomjs做爬虫抓网页 http://www.jb51.net/article/55789.htm 是配合选择器做的 利用 beautifulSoup(文档 :http://www.crummy.com/software/BeautifulSoup/bs4/doc/)这个python模块,可以很轻松的抓取网页内容 # coding=utf-8 import urllib from bs4 import BeautifulSoup url ='http://www.baidu.

  • Python爬虫beautifulsoup4常用的解析方法总结

    摘要 如何用beautifulsoup4解析各种情况的网页 beautifulsoup4的使用 关于beautifulsoup4,官网已经讲的很详细了,我这里就把一些常用的解析方法做个总结,方便查阅. 装载html文档 使用beautifulsoup的第一步是把html文档装载到beautifulsoup中,使其形成一个beautifulsoup对象. import requests from bs4 import BeautifulSoup url = "http://new.qq.com/o

  • Python爬虫包 BeautifulSoup 递归抓取实例详解

    Python爬虫包 BeautifulSoup  递归抓取实例详解 概要: 爬虫的主要目的就是为了沿着网络抓取需要的内容.它们的本质是一种递归的过程.它们首先需要获得网页的内容,然后分析页面内容并找到另一个URL,然后获得这个URL的页面内容,不断重复这一个过程. 让我们以维基百科为一个例子. 我们想要将维基百科中凯文·贝肯词条里所有指向别的词条的链接提取出来. # -*- coding: utf-8 -*- # @Author: HaonanWu # @Date: 2016-12-25 10:

  • python爬虫之BeautifulSoup 使用select方法详解

    本文介绍了python爬虫之BeautifulSoup 使用select方法详解 ,分享给大家.具体如下: <html><head><title>The Dormouse's story</title></head> <body> <p class="title" name="dromouse"><b>The Dormouse's story</b></

  • Python3实现爬虫爬取赶集网列表功能【基于request和BeautifulSoup模块】

    本文实例讲述了Python3实现爬虫爬取赶集网列表功能.分享给大家供大家参考,具体如下: python3爬虫之爬取赶集网列表.这几天一直在学习使用python3爬取数据,今天记录一下,代码很简单很容易上手. 首先需要安装python3.如果还没有安装,可参考本站前面关于python3安装与配置相关文章. 首先需要安装request和BeautifulSoup两个模块 request是Python的HTTP网络请求模块,使用Requests可以轻而易举的完成浏览器可有的任何操作 pip insta

随机推荐