四大对象种类
BeautifulSoup将复杂HTML文档转换成一个复杂的树形结构。
每个节点都是Python对象,我们只用根据节点进行查询就可以了,因为解析工作交给了框架本身。所有对象可以归纳为4种:
- Tag
- BeautifulSoup
- NavigableString
- Comment
(1)Tag对象
举几个例子
<title>The Dormouse's story</title>
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
上面的title a 等等 HTML 标签加上里面包括的内容就是 Tag。
在前几次的文章中,我们就是通过Tag来获取信息的。
如获得标签<title>
print soup.title
#<title>The Dormouse's story</title>
我们可以利用 bs4加标签名轻松地获取这些标签的内容,比用正则表达式求方便很多。
不过有一点是,它查找的是在所有内容中的第一个符合要求的标签,如果要查询所有的标签,则需要使用find()和find_all()(findAll())这两个函数,后面两个函数在目前的代码中来看功能和语法是一样的,如果后期有什么区别,我会再返回来讲的。
for item in soup.findAll('a'):
print item,'\n'
print soup.find('a')
print soup.find_all('a', limit = 1)[0]
# limit 是取前x项的意思,find()实际等于limit=1的情况,只是find_all()返回的是列表
print soup.find_all(lambda tag: len(tag.attrs) == 2)
# BS4允许我们把特定函数类型当做findAll函数的参数,唯一的限制是这些函数必须把一个标签当做参数且返回结果为bool类型
我们可以验证一下这些对象的类型
print type(soup.a)
# <class 'bs4.element.Tag'>
对于Tag而言,有两个很重要的属性,一个是name,一个是attrs。
name
print soup.name
print soup.head.name.
# [document]
# head
soup 对象本身比较特殊,它的 name 即为 [document],对于其他内部tag,输出的值便为标签本身的名称。
attrs
print soup.p.attrs
# {'class': ['title'], 'name': 'dromouse'}
在这里,我们把 p 标签的所有属性打印输出了出来,得到的类型是一个字典。
如果我们想要单独获取某个属性,可以这样,例如我们获取它的 class 叫什么
print soup.p.attrs
# {'class': ['title'], 'name': 'dromouse'}
还可以这样,利用get方法,传入属性的名称,二者是等价的
print soup.p.get('class')
# ['title']
我们可以对这些属性和内容等等进行修改,例如
soup.p['class']="newClass"
print soup.p
# <p class="newClass" name="dromouse"><b>The Dormouse's story</b></p>
还可以对这个属性进行删除,例如
del soup.p['class']
print soup.p
#<p name="dromouse"><b>The Dormouse's story</b></p>
不过,对于修改删除的操作,不是我们的主要用途,在此不做详细介绍了,如果有需要,请查看前面提供的官方文档。
同时我们也可以通过这个attrs去更加详细地过滤标签
print soup.find_all('a', {"class" : "sister"})
# 限制了标签为a,且属性中的class = sister
# "sister的位置也可以是一个re.compile("")的对象,
注意,find_all() 返回结果可能为
<class 'bs4.element.ResultSet'> 这里是字典外套了一个列表
查看 textPid = pid[0] ,输出:<class 'bs4.element.Tag'>
查看tag内容:print(textPid.get_text()) ,或者print(textPid.text())
(2)BeautifulSoup对象
BeautifulSoup 对象表示的是一个文档的全部内容。大部分时候,可以把它当作 Tag 对象,是一个特殊的 Tag,我们可以分别获取它的类型,名称,以及属性来感受一下。
print type(soup.name)
# <type 'unicode'>
print soup.name
# [document]
print soup.attrs
# {}
(3)NavigableString对象
我们已经得到了标签,用 .string 即可获得标签内部的文字。
如获得标签<p>中的内容
print soup.p.string
#The Dormouse's story
这样我们就轻松获取到了标签里面的内容,想想如果用正则表达式要多麻烦。它的类型是一个 NavigableString,翻译过来叫 可以遍历的字符串。
来检查一下它的类型
print type(soup.p.string)
# <class 'bs4.element.NavigableString'>
navigablestring可以很简单地转换为unicode,和string是几乎一样的。
实例:unicode_string = unicode(tag.string)
(4)Comment对象
Comment 对象是一个特殊类型的 NavigableString 对象,其实输出的内容仍然不包括注释符号,但是如果不好好处理它,可能会对我们的文本处理造成意想不到的麻烦。
我们找一个带注释的标签
print soup.a
print soup.a.string
print type(soup.a.string)
运行结果如下
<a class="sister" href="http://example.com/elsie" id="link1"><!-- Elsie --></a>
Elsie
<class 'bs4.element.Comment'>
a 标签里的内容实际上是注释,但是如果我们利用 .string 来输出它的内容,我们发现它已经把注释符号去掉了,所以这可能会给我们带来不必要的麻烦。
另外我们打印输出下它的类型,发现它是一个 Comment 类型,所以,我们在使用前最好做一下判断,判断代码如下
if type(soup.a.string)==bs4.element.Comment:
print soup.a.string
上面的代码中,我们首先判断了它的类型,是否为 Comment 类型,然后再进行其他操作,如打印输出。
# -*- coding: utf-8 -*-
# @Author: HaonanWu
# @Date: 2016-12-24 17:27:43
# @Last Modified by: HaonanWu
# @Last Modified time: 2016-12-24 19:53:47
from bs4 import BeautifulSoup
html = """
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title" name="dromouse"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1"><!-- Elsie --></a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""
def Tree_test(soup):
print soup.prettify()
def Tag_test(soup):
print soup.title
print type(soup.a)
for item in soup.findAll('a'):
print item,'\n'
print soup.find('a')
print soup.find_all('a', limit = 1)
print soup.name
print soup.head.name
print soup.p.attrs
print soup.p.get('class')
def string_test(soup):
print soup.p.string
print type(soup.p.string)
def bs_test(soup):
print soup.name
print soup.attrs
print type(soup.name)
def comment_test(soup):
print soup.a
print soup.a.string
print type(soup.a.string)
if __name__ == '__main__':
soup = BeautifulSoup(html, 'lxml')
---------------------
作者:SuPhoebe
来源:CSDN
参考:https://blog.csdn.net/u013007900/article/details/53861207
【笔记】
# coding: utf-8
import requests, re
from bs4 import BeautifulSoup
headers = {
'自己填'
}
url = "https://www.geonames.org/search.html?q=America"
session = requests.Session()
session.headers.update(headers)
html = session.get(url)
print(html)
if html.status_code == 200 and html.text:
#print(html.text)
soup = BeautifulSoup(html.text, 'lxml')
# table = soup.findAll('table',class_='restable')
# print(table)
trs = soup.find_all(name='tr')
print(type(trs[6])) # <class 'bs4.element.Tag'>
line = trs[6].string
print(type(line)) # <class 'NoneType'>
line = trs[6].get_text() # <class 'str'>
print(type(line))
print(line)
结果输出:
<Response [200]>
<class 'bs4.element.Tag'>
<class 'NoneType'>
<class 'str'>
1 China Althydulydveldid Kina,Alþýðulýðveldið Kína,An tSin,An tSín,Caina,Caina Sin,Cayina,Chaina,China,Chin...35.0105.0China, independent political entitypopulation 1,330,044,000
N 35° 0' 0''E 105° 0' 0''