Python爬虫之Beautiful Soup库及大学排名爬取

 

Beautiful Soup库是解析、遍历、维护“标签树”的功能库。Beautiful Soup库也叫beautifulsoup4 或 bs4。但主要还是用BeautifulSoup类,约定引用方式如下:

from bs4 import BeautifulSoup
import bs4

Beautiful Soup库解析器

soup = BeautifulSoup('<html>data</html>','html.parser')

bs4的HTML解析器 BeautifulSoup(mk,'html.parser') 安装bs4库

lxml的HTML解析器 BeautifulSoup(mk,'lxml') pip install lxml

lxml的XML解析器 BeautifulSoup(mk,'xml') pip install lxml

html5lib解析器 BeautifulSoup(mk,'html5lib') pip install html5lib

 

BeautifulSoup类的基本元素

 

- 任何存在于HTML语法中的标签都可以用soup.<tag>访问获得。当HTML文档中存在多个相同<tag>对应内容时,soup.<tag>返回第一个。

 

- 每个<tag>都有自己的名字,通过<tag>.name获取,字符串类型。

 

- 一个<tag>可以有0或多个属性,字典类型.

 

- NavigableString可以跨越多个层次

 

举例:假设我们获得的某个网页的文本信息如下

 

>>> from bs4 import BeautifulSoup 
>>> soup = BeautifulSoup('<html>data</html>','html.parser')
>>> soup.title  
This is d pyton demo page 
>>> soup.a.name 
'a'
>>> tag = soup.a
>>> tag.attrs
{'id':'link1','class':['py1'], 'href': 'http://....'}
>>>tag.string
'Basic Python'

 

HTML内容遍历方法

 

下行遍历常见属性:

 

.contents 子节点的列表,将<tag>所有儿子节点存入列表

.children 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点

.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

 

# 遍历儿子节点
for child in soup.body.children:
    print(child)
# 遍历子孙节点
for child in soup.body.descendants:
    print(child)

 

上行遍历常见属性:

.parent 节点的父亲标签

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

 

平行遍历常见属性:平行遍历发生在同一个父节点下的各节点间。

 

.next_sibling 返回按照HTML文本顺序的下一个平行节点标签

.previous_sibling 返回按照HTML文本顺序的上一个平行节点标签

.next_siblings 迭代类型,返回按照HTML文本顺序的后续所有平行节点标签

.previous_siblings 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

 

规范输出

.prettify()方法可以使得HTML内容显示更加规范。在每个把标签的结尾田间一个换行符'\n' 。.prettify()可用于标签,方法:<tag>.prettify()。​​​​​​​

print (soup.prettifu()) 
print (soup.a.prettifu())

编码格式

bs4库将任何HTML输入都变成utf‐8编码,因此我们在解析时无障碍。​​​​​​​

>>>soup = BeatifulSoup("<p>中文<\p>",'html.parser')
>>>soup.p.string
'中文' 

 

HTML信息标记方式

超文本 包括声音、图像、视频。对于这类信息的标记便于我们更好的表示。标记后的信息能够增强信息维度,更加有利于程序的理解和存储。

 

信息标记方式可以包括三种: XML、JSON、YAML

XML       Internet上的信息交互与传递

JSON      移动应用云端和节点的信息通信,无注释

YAML     各类系统的配置文件,有注释易读

 

XML(eXtensible Markup Language)​​​​​​​

# XML标签 <name> … </name>
<img src=“china.jpg” size=“10”> … </img>
# 空元素的缩写形式 <name />
<img src=“china.jpg” size=“10” />
# 注释书写形式  <!‐‐ ‐‐>
<!‐‐ This is a comment, very useful ‐‐>

示例:​​​​​​​

<person>
    <firstName>公众号</firstName>
    <lastName>花重锦城</lastName>
    <address>
        <streetAddr>重庆市北碚区</streetAddr>
        <city>重庆市</city>
        <zipcode> 033478 </zipcode>
     </address>
     <prof>Computer System</prof><prof>Security</prof>
</person>

JSON(JavsScript Object Notation)

有类型的键值对 key : value​​​​​​​

#有类型的键值对 key : value
“name” : “公众号花重锦城”
# 其中:“”表示类型,name表示key,‘公众号花重锦城’表示值valu  

 

当value 有多个值时用,号分隔。例如

“name” :['公众号 ', '花重锦城']

键值对嵌套形式​​​​​​​

“name”: {
“FirstName” : “公众号”,
“lastName” : “花重锦城”
}

示例:​​​​​​​

{
  “firstName” : “公众号” ,
  “lastName” : “花重锦城” ,
  “address”  : {
              “streetAddr” : “重庆市北碚区” ,
              “city”  : “重庆市” ,
              “zipcode”  : “033478 ”
              } ,
  “prof”  : [ “Computer System” , “Security” ]
}

YAML (YAML Ain’t Markup Language)

无类型键值对 key:value​​​​​​​

name : “公众号花重锦城”
# 其中:name表示key,‘公众号花重锦城’表示值valu 
通过缩进表达所属关系,通过 表达并列关系​​​​​​​
# 注意缩进
name :
  firstName : 公众号
  lastName : 花重锦城
# 并列关系
name :
‐公众号
‐花重锦城

示例:

firstName : 公众号
lastName : 花重锦城
address  :
    streetAddr : 重庆市北碚区
    city  : 重庆市
    zipcode : 033478
prof  :
‐Computer System
‐Security

信息提取方式

信息的提取也是对网页内容的解析,根据网页的结构和自己需要提取内容的关键标识符号来进行信息的检索,最终得到数据。在网页的解析过程中,我们除了要明确网页信息的表示方式之外,还要利用正则表达式定位关键位置实现信息提取。基于bs4库的HTML内容查找:

>>> soup.findall('a')
>>> soup.findall(['a','b']
# 注意
<tag>(..) 等价于 <tag>.find_all(..)
soup(..)  等价于 soup.find_all(..)

 

实例,中国大学排名爬虫

 

提示: 中文字符的空格填充 chr(12288)​​​​​​​

import requests
import bs4
from bs4 import BeautifulSoup
 
def getHTMLText(url):
    try:
        r = requests.get(url, timeout = 30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""
 
def fillUnivList(ulist, html):
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):
            tds = tr.find_all('td')
            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)))
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0], u[1], u[2], chr(12288)))
 
def main():
    uinfo = []
    url = 'http://www.zuihaodaxue.cn/zuihaodaxuepaiming2016.html'
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 5)
 
if __name__ == "__main__":
    main()
'''out
    排名         学校名称         总分    
    1          清华大学        95.9   
    2          北京大学        82.6   
    3          浙江大学         80 
    4           上海交通大学         78.8
    5            复旦大学            70.9
'''

 

 扫描二维码学习了解更多关于python、机器学习、Linux系统以及开源软件的知识

  

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值