Python 网络爬虫(二、Beautiful Soup 库)

一、Beautiful Soup 库使用案例

requests 库实现了对网页内容的爬取,但是,如何从繁杂的信息中提取正真有价值的数据?
Beautiful Soup 是解析、遍历、维护“标签”树的功能库。
爬取中国最好大学排名2016 的数据:http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html

程序设计步骤:
1、获取大学排名网页内容;
2、提取网页内容中的有用信息到合适的数据结构中;
3、将爬取得大学排名打印、保存;
参考代码:

#-*- coding:utf-8 -*-
#!user/bin/python
import requests
import bs4
from bs4 import BeautifulSoup
def getHTMLText(url):
    try:
        r = requests.get(url,timeout = 30)      # 抓取 HTML 页面内容,超时时间设置为30s
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return(r.text)
    except:
        return"爬取出错"

def fillUnivList(ulist,html):                         # 信息提取,参数 ulist 用于存放数据的列表,html 抓取的网页内容
    soup = BeautifulSoup(html, "html.parser")        # html.parser 为 Beautiful Soup 库解析器
    for tr in soup.find("tbody").children:           # soup.find() 搜索且只返回一个结果
        if isinstance(tr, bs4.element.Tag):           # 判断 tr 是否是 bs4 的标签类型
            tds = tr('td')                            # (..)  等价于.find_all(..)
            ulist.append([tds[0].string, tds[1].string, tds[3].string])

def printUnivList(ulist,num):                         # 对抓取的数据打印
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
    print(tplt.format("排名","学校名称","总分",chr(12288)))
    with open("Sort.txt", 'w') as f:
        f.write(("{0:^10}\t{1:{3}^10}\t{2:^10}\n").format("排名","学校名称","总分",chr(12288)))
        for i in range(num):
            u = ulist[i]
            print(tplt.format(u[0],u[1],u[2],chr(12288)))
            f.write(("{0:^10}\t{1:{3}^10}\t{2:^10}\n").format(u[0],u[1],u[2],chr(12288)))

if __name__ == '__main__':
    unifo = []
    print("输入需要打印的大学数量:")
    num = int(input(">"))              #  打印前 num 名
    url = "http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html"        # 中国最好大学排名
    html = getHTMLText(url)
    fillUnivList(unifo,html)
    printUnivList(unifo,num)

下图为该网页的源代码,从该源代码中,可以看出,我们需要爬取的信息均包含在标签内。所以,要获取信息,首先需要了解HTML 、 标签树的遍历方式和HTML内容的查找方法。

Python 网络爬虫(二、Beautiful Soup 库)_第1张图片

二、HTML 简介

通过以下代码是 https://python123.io/ws/demo.html 的网页源代码:

查看网页源代码的python 代码:

import requests
import bs4
from bs4 import BeautifulSoup
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text                                # demo 为  类型
soup = BeautifulSoup(demo,"html.parser")    # soup 为类型,参数html.parser为HTML解析器
print(soup.prettify())                      #  prettify() 方法为HTML 文本内容增加’\n’,即换行

网页源代码为:

<html>
 <head>
  <title>
   This is a python demo page
  title>
 head>
 <body>
  <p class="title">
   <b>
    The demo python introduces several python courses.
   b>
  p>
  <p class="course">
   Python is a wonderful general-purpose programming language. You can learn Python from novice to professional by tracking the following courses:
   <a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">
    Basic Python
   a>
   and
   <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">
    Advanced Python
   a>
   .
  p>
 body>
html>

从以上代码,可以看出 HTML 的一般格式为:
Python 网络爬虫(二、Beautiful Soup 库)_第2张图片
HTML 通过预定义的 < >……..< / > 标签形式组织不同类型的信息!

其中的标签有:< title>……< /title> < body>….< /body> < p>….< /p> < a>…< /a>

< p class = “title”> … < / p> : p 是标签名称,成对出现;class=”title” 表示属性(0个或者多个)

Python 网络爬虫(二、Beautiful Soup 库)_第3张图片
HTML << 标签树 << 使用 Beautiful Soup 解析

html.parser 表示 Beautiful Soup 库解析器, 一些常用的解析器有:
Python 网络爬虫(二、Beautiful Soup 库)_第4张图片

三、Beautiful Soup 类的基本元素(标签树的遍历方式)
Python 网络爬虫(二、Beautiful Soup 库)_第5张图片

每个< Tag> 都有自己的名字(字符串类型),通过< tag>.name 获取。
soup.title #获取标签title的内容 < title>This is a python demo page< /title>
tag.attrs # 获取标签的属性,每个标 签有0 个或者多个属性,属性为字典类型;
soup.prettify() #为HTML文本<>及其内容增加’\n’,是文本打印美观

< p class = “title”>….< /p>

其中,< > 内的为标签, p 为标签名称,可通过 .name 获取,class = “title” 表示属性,获取方式为:.attrs 表示非属性字符串/注释, 获取方式为: .string

HTML 内容的遍历方法有:

1、标签树的下行遍历:

.contents           : 子节点的列表,将< tag> 所有儿子节点存入列表
.children           : 子节点的迭代类型,与 .contents 类似,用于循环遍历儿子节点
.descendants        : 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

2、标签树的上行遍历:

.parents       :节点的父亲标签
.parents       :节点先辈标签的迭代类型,用于循环遍历先辈节点

3、标签树的平行遍历:

.next_sibling         :返回按照 HTML 文本顺序的下一个平行节点标签
.previous_sibling     :返回按照 HTML 文本顺序的上一个平行节点标签
.nest_siblings        :迭代类型,返回按照 HTML 文本顺序的后续所有平行节点标签
.previous_sibling     :迭代类型,返回按照 HTML 文本顺序的前续所有平行节点标签

例如:遍历标签 body 的儿子节点:

for child in soup.body.children:
    print(child)

Python 网络爬虫(二、Beautiful Soup 库)_第6张图片

平行遍历只能发生在同一个父节点下的各个子节点之间。

四、HTML内容的查找方法

1、信息标记的三种形式

HTML 是通过预定义的< >…< /> 标签形式组织不同类型的信息。在提取信息之前,需要首先了解信息的标记形式:XML、JSON、YAML。

A、XML 信息标记形式为:
< img src=”china.jpg” size = “10”>…< /img>

img 表示名称;src=”china.jpg” size = “10” 表示属性;注释的书写形式为:< !‐‐ This is a comment, very useful ‐‐>

例如:

<person>
   <firstName>TianfirstName>
   <lastName>SonglastName>
   <address>
      <streetAddr>中关村南大街5号streetAddr>
      <city>北京市city>
      <zipcode>100081zipcode>
   address>
   <prof>Computer Systemprof><prof>Securityprof>
person>

B、JSON 信息的标记形式

有类型的键值对: key:value
例如:

{
    “firstName” : “Tian” ,
    “lastName” : “Song” ,
    “address” : {
                  “streetAddr” : “中关村南大街5号” ,
                  “city” : “北京市” ,
                  “zipcode” : “100081”
                 } ,
     “prof” : [ “Computer System” , “Security” ]
}

分别对应了:一个键对应一个值;键值对嵌套;一个键对应对各值(多值用[ , ]组织)三种形式。

C、YAML 的信息标记形式

无类型键值对: key:value
例如:

firstName : Tian
lastName : Song
address :
    streetAddr : 中关村南大街5号
    city : 北京市
    zipcode : 100081
prof :
‐Computer System
‐Security

缩进表示所属关系;-表示并列关系;# 表示注释 ; | 表示整块数据。

三种信息标记形式对比:

XML :可扩展性好,但是繁琐;用于 Internet 上的信息交互与传递。
JSON :信息有类型,适合程序处理( js ),较 XML 简洁;用于移动应用云端和节点的信息通信,无注释。
YAML :信息无类型,文本信息比例最高,可读性性好。用于各类系统的配置文件,有注释易读。

2、基于 bs4 库的HTML内容查找方法

<>.find_all(name, attrs, recursive, string, **kwargs)

∙ name :对标签名称的检索字符串
∙ attrs : 对标签属性值的检索字符串,可标注属性检索
∙ recursive: 是否对子孙全部检索,默认True
∙ string:< >…< />中字符串区域的检索字符串

例如,对网页 https://python123.io/ws/demo.html;
A、查找标签名称为“a” 的标签:

r = requests.get("https://python123.io/ws/demo.html")
r.raise_for_status()
r.encoding = r.apparent_encoding
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
print(soup.find_all("a"))

查找结果是:

[<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic 
Pythona>, <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" 
id="link2">Advanced Pythona>]

B、查找查找标签名称为“a” 和“b”的标签:

soup.find_all(["a","b"])

查找结果是:

[<b>The demo python introduces several python courses.b>, <aclass="py1"href=
"http://www.icourse163.org/course/BIT-268001" id="link1">Basic Pythona>, <a 
class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced 
Pythona>]

C、搜索到所有< a> 标签,并且解析< a>标签格式,提取 href 后的链接格式;

r = requests.get("https://python123.io/ws/demo.html")
r.raise_for_status()
r.encoding = r.apparent_encoding
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all("a"):
    print(link.get("href"))

输出结果为:

http://www.icourse163.org/course/BIT-268001
http://www.icourse163.org/course/BIT-1001870001

3、HTML内容的查找方法的扩展

Python 网络爬虫(二、Beautiful Soup 库)_第7张图片

——摘自:中国大学MOOC 《Python网络爬虫与信息提取》 嵩天老师课件

你可能感兴趣的:(python,Python,网络爬虫)