01_7爬虫网页_BS4

BeautifulSoup

是一个非常优秀的Python扩展库,可以用来从HTML或XML文件中提取我们感兴趣的数据,并且允许指定使用不同的解析器。

一、安装BeautifulSoup

1.1 mac安装bs4

完成安装python3后,直接在命令行使用pip3或者easy_install来安装

1.pip3安装

pip3 install beautifulsoup4

2.easy_install安装

easy_install beautifulsoup4

1.2 win下安装bs4

需要先下载bs4安装包到本地python目录,再执行命令

借鉴网上方法

    python3.4.3 对BeautifulSoup的支持不太好,大多网上都是python2.7 的安装教程,而按那个真是颇费周折。最后,在[https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/](https://www.crummy.com/software/BeautifulSoup/bs4/doc.zh/) 找到了解决方案

     1.下载
        [https://www.crummy.com/software/BeautifulSoup/bs4/download/ ](https://www.crummy.com/software/BeautifulSoup/bs4/download/)
     2.解压至D:\python34   即python安装目录
     3.打开cmd,进入D:\python34\beautifulsoup4-4.4.1  ,这是我的安装路径,这里面有setup.py  文件
     4.cmd中输入 ```Python setup.py install```
     如果行不通,Beautiful Soup的发布协议允许你将BS4的代码打包在你的项目中,这样无须安装即可使用.
     5.测试是否安装好
         5.1输入python,进入python模块
         5.2输入from bs4 import BeautifulSoup检测是否成功。
      另附BeautifulSoup中文文档链接,接下来好好享受爬虫旅程。[https://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html#Quick%20Start](https://www.crummy.com/software/BeautifulSoup/bs3/documentation.zh.html#Quick%20Start)


根据方法执行

1.下载和安装

下载bs4包后,解压至本地python目录

备注:cmd中可通过where python获得本地python路径

2.使用Python setup.py install安装

使用Python setup.py install安装报错,是因为进入当下路径文件夹后,无steup.py文件可供安装。调整1和2步骤,下载最新bs4包4.6版本,进入steup.py文件夹中

下载bs4包后,解压至本地python目录.png

执行命令python setup.py install,正常进入安装流程

安装bs4_1.png

安装bs4_2.png

3.进入python,使用from bs4 import BeautifulSoup查看是否正常

from bs4 import BeautifulSoup_报错.png

查找上述报错解决方法,因为使用python3.6版本,需更换库,把python2的库升级为python3的库
具体:将bs4文件夹和2to3.py同时放到lib中,然后在cmd中定位到lib,运行:2to3.py bs4 -w就好了


2to3.py bs4 -w.png

之后运行报错,操作异常,确认后发现,将bs4文件夹放入lib文件夹中执行错误

--1.beautifulSoup4解压目录中的bs4文件夹C:\Users\xx\AppData\Local\Programs\Python\Python36\beautifulsoup4-4.6.0\beautifulsoup4-4.6.0\bs4
--2. 2to3.pyC:\Users\xx\AppData\Local\Programs\Python\Python36\Tools\scripts
都复制到python的安装目录下的LibC:\Users\xx\AppData\Local\Programs\Python\Python36\Lib文件夹下
进入D:\Python37-32\Lib 目录,并执行2to3.py bs4 -w命令

bs4安装包下bs4文件夹.png
2to3.py文件.png

进入python,使用from bs4 import BeautifulSoup查看是否正常


完成安装,并可正常使用bs4.png

二、BeautifulSoup语法

1.学习基本够用的即可
2.学习2,已完成
3.学习3,待学习搜索文档树、find_all
4.学习4,好的实践

2.1. BeautifulSoup类的基本元素

Tag
Tag 对象与 XML 或 HTML 原生文档中的 tag 相同,表示标签,是最基本的信息组织单元,分别用<>和</>开头和结尾

<Tag>.name : Name 表示标签的名字
<Tag>.attrs: Attributes 表示标签的属性,返回字典形式组织,
<Tag>.string : NavigableString 表示标签内非属性字符串
<Tag>.string: Comment 表示标签内的注释部分

1.tag实例
如上之前已经学过,soup.标签a/p,代表遍历到第一个a标签或者p标签

>>> tag1 = soup.a
>>> print(tag1)
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>
>>> tag2 = soup.p
>>> print(tag2)
<p class="title"><b>The Dormouse's story</b></p>

2.Name实例
类似:当我们通过soup.title.name的时候就可以获得该title标签的名称,即<title>括号中的title

>>> tag1.name
'a'
>>> tag2.name
'p'

3.Attributes 实例

 >>> tag1.attrs
{'href': 'http://example.com/elsie', 'class': ['sister'], 'id': 'link1'}

#在这里,我们把 tag1即a标签的所有属性打印输出了出来,得到的类型是一个字典。
>>> tag2.attrs
{'class': ['title']}

如果我们想要单独获取某个属性,可以这样,例如我们获取它的 class 叫什么

>>> tag2.attrs.get('class')
['title']

我们也可以通过这个attrs去更加详细地过滤标签--find_all
如果想要通过名字得到比一个 tag 更多的内容的时候就需要用 Searching the tree 中描述的方法, 比如 : find_all()

>>> soup.find_all('p')
[<p class="title"><b>The Dormouse's story</b></p>, <p class="story">Once upon a time there were three little sisters; and their names were
<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>,
<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a> and
<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>, <p class="story">...</p>]

4.NavigableString
NavigableString按照字面意义上理解为可遍历字符串,
是BeautifulSoup对象四种类型tag|NavigableString|BeautifulSoap|Comment中的一种

>>> tag1.string
'Elsie'
# tag1即a标签的内容 #
>>> type(tag1.string)
<class 'bs4.element.NavigableString'>
# 知道是一种类型,写明对象类型 NavigableString #
>>> tag2.string
"The Dormouse's story"
>>> type(tag2.string)
<class 'bs4.element.NavigableString'>

5.Comment 实例 (与 NavigableString 的区别)
Comment 对象是一个特殊类型的 NavigableString 对象??还是不太懂

2.2 学习属性和打印语句

2.2.1 学习属性

1.标签选择器

在快速使用中我们添加如下代码

print(soup.title)
print(type(soup.title))
print(soup.head)
print(soup.p)

作用:通过这种soup.标签名 我们就可以获得这个标签的内容
备注:这里有个问题需要注意,通过这种方式获取标签,如果文档中有多个这样的标签,返回的结果是第一个标签的内容,如上面我们通过soup.p获取p标签,而文档中有多个p标签,但是只返回了第一个p标签内容,见2.1.2 打印语句6.属性print(soup.p)打印结果

2.获取名称

当我们通过soup.title.name的时候就可以获得该title标签的名称,即title
print(soup.title.name)

3.获取属性

print(soup.p.attrs['name'])
print(soup.p['name'])

4.获取内容

print(soup.p.string)

结果就可以获取第一个p标签的内容:

The Dormouse's story

5.嵌套选择

见下方 5.属性print(soup.title.parent.name)打印结果
嵌套有 父子节点的概念,通过子.parent=父状态,来嵌套获得父的信息

6.标准选择器

find_all:可以根据标签名,属性,内容查找文档
find_all() 方法搜索当前 tag 的所有 tag 子节点, 并判断是否符合过滤器的条件??

待学习find_all示例

find_all(name,attrs,recursive,text,**kwargs)

其余属性目前未涉及,暂时未关注,可继续回溯‘https://www.cnblogs.com/zhaof/p/6930955.html

2.2.2 打印语句

#-*- coding:utf-8 -*-

from bs4 import BeautifulSoup

html_doc = """ 
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><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> 
"""

soup = BeautifulSoup(html_doc, 'html5lib')

print(soup.prettify())
print(soup.title)
print(soup.title.name)
print(soup.title.string)
print(soup.title.parent.name)
print(soup.p)
print(soup.p["class"])
print(soup.a)
print(soup.find_all('a'))
print(soup.find(id='link3'))
  1. 属性print(soup.prettify())打印结果
    prettify()函数,实现格式化输出:把代码格式给搞的标准一些,符合html代码格式(从.py文件中发现,相关html格式并不规范),使用prettify规范格式,更清楚
C:\Users\sylvia.li\PycharmProjects\untitled\venv\Scripts\python.exe F:/01_python/01_testsamples/bs4_04.py
<html>
 <head>
  <title>
   The Dormouse's story
  </title>
 </head>
 <body>
  <p class="title">
   <b>
    The Dormouse's story
   </b>
  </p>
  <p class="story">
   Once upon a time there were three little sisters; and their names were
   <a class="sister" href="http://example.com/elsie" id="link1">
    Elsie
   </a>
   ,
   <a class="sister" href="http://example.com/lacie" id="link2">
    Lacie
   </a>
   and
   <a class="sister" href="http://example.com/tillie" id="link3">
    Tillie
   </a>
   ;
and they lived at the bottom of a well.
  </p>
  <p class="story">
   ...
  </p>
 </body>
</html>

Process finished with exit code 0

2.属性print(soup.title)打印结果
head标签中的起始于<title>完结于</title>的内容

<title>The Dormouse's story</title>

属性print(soup.head)打印结果
html中起始于<head>完结于</head>的内容

<head><title>The Dormouse's story</title></head>

3.属性print(soup.title.name)打印结果
当我们通过soup.title.name的时候就可以获得该title标签的名称,即<title>括号中的title

title

4.属性print(soup.title.string)打印结果
title标签中string,即<title>The Dormouse's story</title>><中间string部分

The Dormouse's story

5.属性print(soup.title.parent.name)打印结果
title.parent 是指title标签的父标签,是指 head 标签
head.name 可以获得该head标签的名称,即<head>括号中的head

head

6.属性print(soup.p)打印结果
如果文档中有多个这样的标签,返回的结果是第一个标签的内容,如上面我们通过soup.p获取p标签,而文档中有多个p标签,但是只返回了第一个p标签内容起始于<p到/p>为止

<p class="title"><b>The Dormouse's story</b></p>

7.属性print(soup.p["class"])打印结果
第一个P标签中'class'的内容,把class=‘title’中赋给class的内容,字符串‘title’

['title']

8.属性print(soup.a)打印结果
第一个a标签内容起始于<a到/a>为止

<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>

9.属性print(soup.find_all('a'))打印结果
找到所有a标签并打印相关内容

[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

10.属性print(soup.find(id='link3'))打印结果
打印id=link3的标签结果

<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>
  1. 属性soup.select()

练习示例bs4_04.py,学习地址
【目标】
通过采用soup.select()方法,遍历html后获得目标内容。
其中关键点在于,对于所需内容的精准定位,通过()内的语句来实现:

11.1 关键字class
对于html内的内容,可以通过class(赋值给关键字class的类名)来进行定位
soup.select('.class的类名')

直接写成soup.select('.class')报错,因为找不到目标内容

报错TypeError: 'NoneType' object is not callable.png

head
class:*************************
Traceback (most recent call last):
  File "F:/01_python/01_testsamples/bs4_04.py", line 31, in <module>
    print(soup.selecet('.class'))
TypeError: 'NoneType' object is not callable

Process finished with exit code 1

理解格式含义,使用select()遍历和定位的目标是定位到类class对应名称中的内容:上面html中 class=‘sister’目标类名称是sister格式,按照类名查找 sister

print(soup.select(".目标类名称"))

示例见下

#按照类名查找 sister 上面html中 class=‘sister’目标类名称是sister,格式是print(soup.select(".目标类名称"))
print('sister:*************************')
print(soup.select(".sister"))

比如上述例子 会打印处类=sister的内容

sister:*************************
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

参考文档
1.确定遍历目标
2.根据不同目标特性,找到语法格式

11.2 关键字id
按照id名称查找 注意格式 print(soup.select("#目标id名称 "))。目标是id=link3,则写成"#link3"

print('id=link3:*************************')
print(soup.select("#link3"))

打印结果:

[<a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

11.4 组合高级查找
按照id名称查找 x标签中目标id y 格式 print(soup.select("x #y"))

print('P标签id=link2:*************************')
print(soup.select("p #link2"))

打印结果:

P标签id=link2:*************************
[<a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>]

11.3 关键字标签
按照标签查找,注意目标标签名称

print('tag:*************************')
print(soup.select('a'))

打印结果:

tag:*************************
[<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]

综上,在bs4中希望筛选(或者查找)sth方法
1 直接查找
2 find_allfind
3 通过css选择器select()方法

2.2 BeautifulSoup :一些常用功能的使用和测试

点击此处,很喜欢这位小姐姐的文风,可以静下心阅读

2.2.1 关于bs4的解析速度

1.仔细阅读文档后发现,文档解析器对速度至关重要!
2.安装chardet模块
如果没有安装chardet模块,那么光一个网页就要7秒!!(安装方法自行度娘), 还不包括获取网页时间。然而试过后,如过山车一般:,安装了chardet以后7秒变成了一瞬。
ps:然而,用了几天后又变回了7秒,卸载了chardet又变回了一瞬间!

2.2.2 导入方式

BeautifulSoup升级到4以后,导入方法变了,如下:
from bs4 import BeautifulSoup

2.2.3 关于输入文本格式

关于被解析文档的编码格式
1.官方说无论被传入什么编码的文档,都会被统一为unicode
2.实际上有时候我发现,必须以unicode传入才能获得正确结果,这里试验发现,还真的是如此!必须传入decode过的码

    html_doc = open('test-Zhilian-list-page-sm1.html', 'r').read().decode('utf-8')
    # ^ 这个html文件其实是智联招聘搜索页的源码,可以自己保存下来直接试一试。

如下图,最简单一个爬虫示例。如果要用bs4,需要把参数the_pageread()后继续转换编码格式decode('uft-8')

最简单一个爬虫示例.png

2.2.4 关于bs4的文档解析器

又是一个大坑:bs升级到4后,实例化时需要明确指定文档解析器,如:
soup = BeautifulSoup(html_doc, 'lxml')
坑的地方:
1.但是著名的lxml在这里就是个大坑啊,
2.因为它会直接略过html所有没写规范的tag,而不管人家多在乎那些信息
PS:因为这个解析器的事,我少说也折腾了好几个小时才找到原因吧。

【总结】记住,选择 * html5lib*!效率没查多少,最起码容错率强,不会乱删你东西!
soup = BeautifulSoup(html_doc, 'html5lib')

5.# 关于bs4的输出格式 #################
# prettify()官方解释是一律输出utf-8格式,
# 其实却是unicode类型!!所以必须在prettify()里面指定编码。

output = soup.prettify('utf-8')
print repr(output)
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,681评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,710评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,623评论 0 334
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,202评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,232评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,368评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,795评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,461评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,647评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,476评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,525评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,226评论 3 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,785评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,857评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,090评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,647评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,215评论 2 341

推荐阅读更多精彩内容