python爬虫实战之旅( 第三章:数据解析(bs4法))

上接:第三章:数据解析(正则法)
下接:第三章:数据解析(xpath法)

1.数据解析步骤

  • 标签定位
  • 提取标签,标签属性中存储的数据值

2.bs4数据解析的原理

  • 实例化一个BeautifulSoup对象,并且将页面源码数据加载到该对象中
  • 通过调用BeautifulSoup对象中相关的属性或者方法进行标签定位和数据提取

环境安装

  • pip install bs4
  • pip install lxml
    在这里插入图片描述

使用实例化BeautifulSoup

  • from bs4 import BeautifulSoup
  • 对象的实例化
    • 方法①:将本地的html文档中的数据加载到该对象中

用于测试的text.html如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>此页面以作为测试</title>
</head>
<body>
<p>body 元素的内容会显示在浏览器中。</p>
<p>title 元素的内容会显示在浏览器的标题栏中。</p>
</body>
</html>

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

if __name__ == "__main__":
    #将本地的html文档中的数据加载到该对象中
    fp =open('./test.html','r',encoding='utf-8')
    soup = BeautifulSoup(fp,'lxml')
    print(soup)
    pass

输出结果:
在这里插入图片描述

  • 方法②:将互联网上获取的页面源码加载到该对象中(实际运用得更多)
    主要用到得语句为
page_text = response.text
soup = BeautifulSoup(page_text,'lxml')

3.bs4中提供的方法和属性:

暂时仍以本地的text.html文件为例——

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>此页面以作为测试</title>
</head>
<body>
    <div>
        <p>百里守约</p>
    </div>
    <div class="song">
        <p>李清照</p>
        <p>王安石</p>
        <p>苏轼</p>
        <p>柳宗元</p>
        <a href="http://www/song.com/" title="赵匡胤" target="_self">
            <span>this is span</span>
            宋朝时最强大内王朝,不是军队的强大,而是经济很强大,国民都很有钱</a>
        <a href="" class="du">总为浮云能避日,长安不见使人愁</a>
        <img src="http://www.baidu.com/moinv.jpg" alt="" />
        </div>
    <div class="tang">
        <ul>
            <li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
            <li><a href="http://www.163.com" title="qin">秦时明月汉时关,万里长征人未还,但使龙城飞将在,不教胡马度阴山</a></li>
            <li><a href="http://www.126.com" title="qi">岐王宅里寻常见,崔久堂前几度闻,正是江南好风景,落花时节又逢君</a></li>
            <li><a href="http://www.sina.com" title="du">杜甫</a></li>
            <li><a href="http://www.dudu.com" title="du">杜牧</a></li>
            <li><b>happy</b></li>
            <li><i>hello world!</i></li>
            <li><a herf="http://www.haha.com" id="feng">凤凰台上凤凰游,凤去台空江自流,吴宫花草埋秦径,晋代衣冠成古丘</a></li>
        </ul>
    </div>
</body>
</html>

①soup.tagNme

soup.tagName 返回的是html中第一次出现的tagName标签内容
在这里插入图片描述

②soup.find()

find('tagName'):等同于soup.tagName,只返回第一次出现的标签内容

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

if __name__ == "__main__":
    #将本地的html文档中的数据加载到该对象中
    fp =open('./test.html','r',encoding='utf-8')
    soup = BeautifulSoup(fp,'lxml')
    print(soup.a)#soup.tagName 返回的是html中第一次出现的tagName标签
    print("------分割线---------")
    print(soup.div)
    print("------分割线---------")
    print(soup.find('div'))
    pass

在这里插入图片描述
soup.find()也可以做html网页中class得定位,不过写的时候要注意class带下划线“class_”:

print(soup.find('div',class_='song'))

输出样例:
在这里插入图片描述
当然其他的属性也可以:

print(soup.find('div',class_/id/attr='song'))

③soup.find_all()

可以找到符合要求的所有标签,返回一个列表。

④soup.select()

参数可以放置某种选择器(类选择器/标签选择器/id选择器等等),返回一个列表
以类选择器为例:
在这里插入图片描述
select也可以用于层级选择器
比如这里只想输出:
<li><a href="http://www.baidu.com" title="qing">清明时节雨纷纷,路上行人欲断魂,借问酒家何处有,牧童遥指杏花村</a></li>
分析这句话在html当中的结构位置,是在tang这个类中的li层级的a标签中的第一个,所以将代码部分输出改为:

print(soup.select('.tang>ul>li>a')[0])

注意这里的'>'表示一个层级,要想在多个层级中找所有a标签的内容可以把>换为空格' ',即不再只针对当前的li层级进行查找。

print(soup.select('.tang>ul a')[0])

输出:
在这里插入图片描述

4.标签之间的数据爬取

①.获取标签之间的文本数据

soup.a.text/string/get_text()
  • text/get_text():可以获取某一个标签中所有的文本内容
  • string只可以获取当前标签下的直系内容

如图所示
在这里插入图片描述
检查text.html文件中可以看到,div板块是没有直系内容的。
在这里插入图片描述

②.获取标签中属性值

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

if __name__ == "__main__":
    #将本地的html文档中的数据加载到该对象中
    fp =open('./test.html','r',encoding='utf-8')
    soup = BeautifulSoup(fp,'lxml')
    print(soup.select('.tang > ul a')[0]['href'])
    pass

输出:

http://www.baidu.com

检查test.html代码信息一致

5.代码实战:爬取三国演义小说所有的章节标题和章节内容

选用网址:https://www.shicimingju.com/book/sanguoyanyi.html
在这里插入图片描述

首先需要理解标签之间的层级关系:

  • 可以定位到一个章节标题,发现他是li>a的一个标签中,而其中的文本内容就是我们要解析的章节标题,其中href对应的url就是我们要找的章节内容对应的url
  • 因为章节是一个列表的形式,要批量获取代码信息,选用select()函数就很好

鼠标右键——检查——
在这里插入图片描述

但这里要注意网站对于中文的编码形式,gzip是一种压缩文件,解码的时候要用utf-8转码中文。
在这里插入图片描述
代码:

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

if __name__ == "__main__":
    #UA伪装
    headers = {
    
    
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.11 Safari/537.36'
    }
    #对首页的页面数据进行爬取
    url='https://www.shicimingju.com/book/sanguoyanyi.html'
    page_text=requests.get(url=url,headers=headers)
    #因为原网站使用了gzip压缩文件,直接用text获取的中文将是乱码,所以要先转码
    page_text.encoding='utf-8'
    page_text=page_text.text
    #在首页中解析出章节的标题和详情页的url
    #1.在实例化BeatifulSoup对象,需要将页面源码数据加载到该对象中
    soup=BeautifulSoup(page_text,'lxml')
    #2.解析章节标题和详情页的url
    li_list = soup.select('.book-mulu > ul >li')
    fp=open('./sanguoyanyi.txt','w',encoding='utf-8')
    for li in li_list:
        title = li.a.string
        detail_url = 'http://www.shicimingju.com'+li.a['href']
        detail_page_text = requests.get(url=detail_url,headers=headers)
        detail_page_text.encoding='utf-8'
        detail_page_text=detail_page_text.text
        #3.解析出详情页中相关的章节内容
        detail_soup = BeautifulSoup(detail_page_text,'lxml')
        #属性定位
        div_tag = detail_soup.find('div',class_='chapter_content')
        content=div_tag.text
        # 持久化存储
        fp.write(title+':'+content+'\n')
        print(title)
        pass
    print("爬取数据成功!")
    pass

输出:
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/KQwangxi/article/details/114012532
今日推荐