Skip to content

Latest commit

 

History

History
450 lines (346 loc) · 13.4 KB

File metadata and controls

450 lines (346 loc) · 13.4 KB

python爬虫学习(二)Beautiful Soup

0.说明

该笔记本主要根据 北京理工大学嵩天老师的课程 Python网络爬虫与信息提取 记录而成

Beautiful Soup库的官方文档请参考 Beautiful Soup

Beautiful Soup首次尝试

import requests
from bs4 import BeautifulSoup

url = 'http://python123.io/ws/demo.html'
r = requests.get(url)
page = r.text
soup = BeautifulSoup(page, "html.parser")

# 展示soup标签树
# print(soup.prettify())
# 结果 (此处不展示)

# 展示第一个a标签
# print(soup.a)
# 结果:<a class="py1" href="http://www.icourse163.org/course/BIT-268001" id="link1">Basic Python</a>

# 展示第一个a标签的属性值
# print(soup.a.attrs)
# 结果 {'id': 'link1', 'href': 'http://www.icourse163.org/course/BIT-268001', 'class': ['py1']}

# 展示链接属性
# print(soup.a.attrs['href'])
# 结果 http://www.icourse163.org/course/BIT-268001

# 显示a标签的内容
# print(soup.a.string)
# 结果: Basic Python

# 显示标签名字
# print(soup.a.name)
# 结果:a

Beautiful Soup库的介绍、理解、使用

Beautiful Soup库是解析、遍历、维护“标签树”的功能库

使用方式: from bs4 import BeatifulSoup # 或者 import bs4 soup = BeatifulSoup('data', 'html.parser') 简单的说,我们可以将BeatifulSoup类当成一个HTML/XML文档的全部内容

Beautiful Soup库的解析器

解析器 使用方法 条件
bs4的HTML解析器 BeatifulSoup(mk, 'html.parser') 安装bs4库
lxml的HTML解析器 BeatifulSoup(mk, 'lxml') pip install lxml
lxml的XML解析器 BeatifulSoup(mk, 'xml') pip install lxml
html5lib的解析器 BeatifulSoup(mk, 'html5lib') pip install html5lib

Beautiful Soup类的基本元素

基本元素 说明
Tag 标签,最基本的信息组织单元,分别用<>和标明开头和结尾
Name 标签的名字, < p>...< /p>的名字是'p', 格式:< tag>.name
Attributes 标签的属性,字典形式组织,格式: < tag>.attrs
NavigableString 标签内非属性字符串,<> ...中字符串,格式:< tag>.string
Comment 标签内字符串的注释部分,一种特殊的Comment类型

标签树的下行遍历

属性 说明
.contents 子节点的列表,将< tag>所有儿子节点存入列表
.children 标签的名字, < p>...< /p>的名字是'p', 格式:< tag>.name
.descendants 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

标签树的上行遍历

属性 说明
.parent 节点的父亲标签
.parents 节点先辈标签的迭代类型,用于循环遍历先辈节点

标签树的平行遍历

请注意,所有的平行便利必须发生在同一个父节点下。

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

更加“友好”的输出html页面

使用prettify方法

print(soup.prettify())

总结:Beautiful Soup库

bs4库的基本元素:

Tag, Name, Attributes, NavigableString, Comment

bs4库的遍历功能:

下行遍历: .contents .children .descendents

上行遍历: .parent .parents

中行遍历: .next_sibling .previous_sibling .next_siblings .previous_siblings

import requests
from bs4 import BeautifulSoup

url = 'http://python123.io/ws/demo.html'
r = requests.get(url)
page = r.text
soup = BeautifulSoup(page, "html.parser")

# 标签树的遍历

# 查看head标签里面的内容
# print(soup.head)
# 结果:<head><title>This is a python demo page</title></head>

# 查看body标签里面的内容
# print(soup.body)
# 结果:body标签的内容

# 查看body标签里面的内容,以列表形式返回
# print(soup.body.contents)
# 结果:...(自行尝试)

# 查看body标签里面的内容的长度
# print(len(soup.body.contents))
# 结果: 5


# 便利儿子节点/便利子孙节点类似
#for child in soup.body.children:
    #print(child)
# 结果: 自行查看

# 查看a标签的父亲节点
# print(soup.a.parent)
# 结果: <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>

# 查看a标签的所有父亲节点,会一层一层,直至最后的html
# for parent in soup.a.parents:
#     if parent is None:
#         因为便利过程会一直持续到soup本身,但是soup本身没有.name是属性,所以我们直接打印它,就是[document]
#         print(parent)
#     else:
#         print(parent.name)
# 结果   p body html [document]


# 查看a标签后续的平行标签们
#for slibing in soup.a.next_siblings:
    #print(slibing)
# 结果:(3个)  and   <a class="py2" href="http://www.icourse163.org/course/BIT-1001870001" id="link2">Advanced Python</a>  .

# 更加“友好”的输出html页面
# print(soup.prettify())

通过Beautiful Soup库对信息进行提取和处理

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

返回一个列表类型,存储查找结果。

name: 对标签名称的检索字符串。【可以是列表,可以是True】

attrs:对标签属性值的检索字符串,可以标注属性检索

recursive:是否对子孙节点全部检索,默认为True

string:< >...< />中字符串区域的检索字符串

另外,请谨记

(...)等价于 .find_all(..)

soup(...)等价于 soup.find_all(..)

扩展方法

方法 说明
<>.find() 搜索且只返回一个结果,字符串类型,同.find_all()参数
<>.find_parents() 在先辈节点中搜索,返回列表类型,同.find_all()参数
<>.find_parent() 在先辈节点中搜索,只返回一个结果,字符串类型,同.find_all()参数
<>.find_next_siblings() 在后续平行节点中搜索,返回列表类型,同find_all()参数
<>.find_next_sibling() 在后续平行节点中搜索,只返回一个结果,同.find_all()参数
<>.find_previous_siblings() 在前序平行节点中搜索,返回列表类型,同.find_all()参数
<>.find_previous_sibling() 在前序平行节点中搜索,只返回一个结果,同.find_all()参数
import requests
import re
from bs4 import BeautifulSoup

url = 'http://python123.io/ws/demo.html'
r = requests.get(url)
page = r.text
soup = BeautifulSoup(page, "html.parser")

# 通过find_all方法找出所有的a,b标签

# for link in soup.find_all(['a', 'b']):
#     print(link)

# 找到所有p标签中,含有course字符串的标签

# for link in soup.find_all('p', 'course'):
#     print(link)

# 直接查找id = link1的标签
# print(soup.find_all(id='link1'))

# recursive置位False表示soup的儿子节点中没有a标签,而在其子孙节点中才有
# print(soup.find_all('a',recursive=False))
# 结果 []

# 检索soup中含有python字符串的文本内容
# print(soup.find_all(string=re.compile("python")))
# 结果:['This is a python demo page', 'The demo python introduces several python courses.']

实战:中国大学排名定向爬取

思路分析

功能分析

输入:大学排名URL链接

输出:大学排名信息的屏幕输出

技术路线:requests-bs4

定向爬虫:仅对输入URL进行爬取,不扩展爬取

format函数粗略了解

小技巧

对于中文不对齐问题,我们可以采用中文字符的空格填充chr(12288)|

import requests
from bs4 import BeautifulSoup
import bs4

# 定义获取soup的函数
def getHTML(url):
    try:
        r = requests.get(url, timeout=30)
        # 产生异常信息
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        print('爬取失败!')

# 处理获得的soup,获取我们需要的content
def dealSoup(ulist, page):
    count = 1;
    temp = [];
    soup = BeautifulSoup(page, "html.parser")
    # 获取了所有大学排名的列表,但是还是html格式,接下来,我们需要解析这些格式的数据   
    tr = soup.find_all('tr')[1:]
    for tds in tr:
        td = tds.find_all('td')[1:]
        temp.append(count)
        # 此时的每个td都是单独的一个学校,包含了排名、分数等信息
        for i in td:
            temp.append(i.string)
        ulist.append(temp)
        temp = []
        count = count + 1
    return

# 定义一个显示函数 主要使用fomat函数
def printUniverList(ulist, num):
    # 定义一个输出模板的变量  
    tplt = "{0:^10}\t{1:{13}^10}\t{2:^10}\t{3:^10}\t{4:^10}\t{5:^10}\t{6:^10}\t{7:^10}\t{8:^10}\t{9:^10}\t{10:^10}\t{11:^10}\t{12:^10}"
    print(tplt.format("排名", "学校名称", "省份", "总分", "生源质量", "培养结果", "科研规模", "科研质量", "顶尖成果", "顶尖人才", "科技服务", "成果转化", "学生国际化",chr(12288)))
#     tplt = "{0:^10}\t{1:{4}^10}\t{2:^10}\t{3:^10}\t{4:^10}"
#     print(tplt.format("排名","学校名称","省份", "总分", chr(12288)))
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0], u[1], u[2], u[3], u[4], u[5], u[6], u[7], u[8], u[9], u[10], u[11], u[12], chr(12288)))

# 入口函数
if __name__ == "__main__":
    uinfo = []
    url = "http://zuihaodaxue.cn/zuihaodaxuepaiming2017.html"
    page = getHTML(url)
    dealSoup(uinfo, page)
    printUniverList(uinfo, 10)
    排名    	   学校名称   	    省份    	    总分    	   生源质量   	   培养结果   	   科研规模   	   科研质量   	   顶尖成果   	   顶尖人才   	   科技服务   	   成果转化   	  学生国际化   
    1     	   清华大学   	    北京    	  94.0    	  100.0   	  97.70%  	  40938   	  1.381   	   1373   	   111    	 1263428  	  613524  	  7.04%   
    2     	   北京大学   	    北京    	  81.2    	  96.1    	  97.61%  	  39853   	  1.327   	   1137   	    90    	  470237  	  31652   	  6.16%   
    3     	   浙江大学   	    浙江    	  77.8    	  87.2    	  97.91%  	  44509   	  1.109   	   921    	    88    	 1107921  	  23240   	  4.67%   
    4     	  上海交通大学  	    上海    	  77.5    	  89.4    	  98.62%  	  44674   	  1.134   	   836    	    79    	  796668  	  94339   	  6.30%   
    5     	   复旦大学   	    上海    	  71.1    	  91.8    	  97.85%  	  28205   	  1.355   	   758    	    57    	  246629  	   6221   	  6.78%   
    6     	 中国科学技术大学 	    安徽    	  65.9    	  91.9    	  95.20%  	  20169   	  1.502   	   749    	    40    	  69617   	    0     	  1.02%   
    7     	   南京大学   	    江苏    	  65.3    	  87.1    	  98.60%  	  23308   	  1.344   	   610    	    34    	  408221  	   647    	  4.63%   
    8     	  华中科技大学  	    湖北    	  63.0    	  80.6    	  95.58%  	  26199   	  1.202   	   645    	    34    	  486917  	   5401   	  4.19%   
    9     	   中山大学   	    广东    	  62.7    	  81.1    	  92.77%  	  26422   	  1.247   	   565    	    46    	  212530  	   1373   	  4.15%   
    10    	 哈尔滨工业大学  	   黑龙江    	  61.6    	  76.4    	  95.20%  	  26672   	  1.005   	   550    	    23    	 1666191  	   4886   	  1.98%