tenliu的爬虫(8)-页面提取之beautifulsoup

历史回顾

页面提取已经总结了xpath(lxml库)、正则(re库),我最先接触并且常用的是xpath和正则,这两个的组合完全满足页面解析需求,所以beautifulsoup使用的比较少。

并且个人感觉beautifulsoup就是鸡肋,但是也有不少人主要使用这个库,现在总结一下python的beautifulsoup库的使用方法。

安装

pip install beautifulsoup4

介绍

加载html

我们抓取一个页面,并且使用BeautifulSoup加载页面,然后使用prettify格式化打印一下页面源码。

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import urllib
import urllib2
import requests
import sys
from bs4 import BeautifulSoup

reload(sys) 
sys.setdefaultencoding('utf8')

def first():
	url = "http://www.tenliu.top/index.php/2018/01/09/%E7%88%AC%E8%99%AB-requests%E5%AD%A6%E4%B9%A0/"
	page = requests.get(url).text
	soup = BeautifulSoup(page,"lxml")
	print soup.prettify()
	
if __name__=="__main__":
	first()	

可以看到BeautifulSoup(page,"lxml")加载html页面,但是加载方法不止这一种,如下:

解析器使用方法优势劣势
Python标准库BeautifulSoup(markup, “html.parser”)Python的内置标准库执行速度适中文档容错能力强Python 2.7.3 or 3.2.2)前 的版本中文档容错能力差
lxml HTML 解析器BeautifulSoup(markup, “lxml”)速度快文档容错能力强需要安装C语言库
lxml XML 解析器BeautifulSoup(markup, [“lxml”, “xml”])BeautifulSoup(markup, “xml”)速度快唯一支持XML的解析器需要安装C语言库
html5libBeautifulSoup(markup, “html5lib”)最好的容错性以浏览器的方式解析文档生成HTML5格式的文档速度慢不依赖外部扩展

四种对象类型

beautiful soup将html文档转成树形结构:beautiful soup节点分成四种对象

  • Tag,就是html标签
  • NavigableString,我的理解就是html标签的文字。
  • BeautifulSoup,就是html文档的全部内容,可视为Tag,没什么好讲的
  • Comment,文档的注释部分。

前面三个类型,我们后面会融合讲解,说明一下Comment,在我看来是鸡肋,但是既然是总结,总要解释一下:

>>> markup = '''<div>this is string</div><b><!--Hey, buddy. Want to buy a used parser?--></b>'''
>>> s = BeautifulSoup(markup)
>>> s.div.string
u'this is string'
>>> s.b.string
u'Hey, buddy. Want to buy a used parser?'
>>> type(s.b.string)
<class 'bs4.element.Comment'>
>>> type(s.div.string)
<class 'bs4.element.NavigableString'>

定位节点

如何定位html标签才是重点,我们先加载一个待解析的页面

>>> import requests
>>> from bs4 import BeautifulSoup
>>> url = "http://www.tenliu.top/index.php/2018/01/09/%E7%88%AC%E8%99%AB-requests%E5%AD%A6%E4%B9%A0/"
>>> page = requests.get(url).text
>>> soup = BeautifulSoup(page,"lxml")

通过标签名称定位

选择html第一个a标签

>>> soup.a
<a class="skip-link screen-reader-text" href="#content">\u8df3\u81f3\u5185\u5bb9</a>

加入节点关系

选择html的body的第一个a标签

>>> soup.body.a
<a class="skip-link screen-reader-text" href="#content">\u8df3\u81f3\u5185\u5bb9</a>

选择多个标签

选择html页面所有a标签

>>> soup.find_all('a')

选择html页面所有a标签和b标签

>>> soup.find_all(['a','b'])

加入正则表达式(标签名)

选择所有以b开头的html标签

>>> import re
>>> soup.find_all(re.compile('^b'))

通过属性的键值选择标签

选择属性rel等于home的所有标签

>>> soup.find_all(rel="home")
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]

选择属性rel等于home的所有a标签

>>> soup.find_all("a",rel="home")
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]

加入正则表达式(属性)

>>> soup.find_all(rel=re.compile('hom'))
[<a href="http://www.tenliu.top/" rel="home">TenLiu\u4e2a\u4eba\u7f51\u7ad9</a>]

节点内文本

string

.string,如果tag只有一个 NavigableString 类型或tag类型的子节点,那么这个tag可以使用 .string 得到文本内容

>>> markup = '''<p><b>aaaa</b></p><div><b>bbbb</b><b>cccc</b></div>'''
>>> s = BeautifulSoup(markup)
>>> s
<html><body><p><b>aaaa</b></p><div><b>bbbb</b><b>cccc</b></div></body></html>
>>> s.p
<p><b>aaaa</b></p>
>>> s.p.string
u'aaaa'
>>> s.div.string
>>> 

strings

.strings,如果tag包含了多个子节点,例如上面的div标签,本文内容何如提取呢?

>>> for string in s.div.strings:
...     print string
... 
bbbb
cccc

节点属性

.attrs

>>> soup.p.a.attrs
{'href': 'http://www.tenliu.top/', 'rel': ['home']}
>>> soup.p.a.attrs['href']
'http://www.tenliu.top/'
>>> soup.p.a['href']
'http://www.tenliu.top/'

其他

  • tag的 .contents 属性可以将tag的所有直接子节点以列表的方式输出
  • 通过tag的 .children 生成器,可以对tag的所有直接子节点进行循环
  • .descendants 属性可以对所有tag的子孙节点进行递归循环
  • ······

就到这里吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值