豆瓣Top250:Python爬虫+数据可视化

2023-10-29

前言

刚入门python,数据库,html,寻思着学点有意思的东西。就在无聊之时无意间在B站上看到了爬虫视频,本以为爬虫入门门槛很高。但是老师讲解清晰细腻,兴趣盎然。视频中还有很多基础讲解,非常适合入门爬虫的新手,几乎是零基础入门爬虫的绝佳体验。于是参考B站Python爬虫基础5天速成(2021全新合集)Python入门+数据可视化学习制作,经过大概一个周的练习思考,以下是我学习过程中的心得体会,由于整个项目太大,部分代码未做展示,完整项目已上传豆瓣Top250Python爬虫+数据可视化.zip。感兴趣或者有疑惑地小伙伴评论区见。

数据爬取

from bs4 import BeautifulSoup       # 网页解析,获取数据
import re                           # 正则表达式,进行文字匹配
import urllib.request as urlre      # 指定rul,获取网页数据
import xlwt                         # 操作Excel
import sqlite3                      # 操作数据库

测试类库

1.urllib.request( 获取网页HTML源代码)

import urllib.request

url = 'https://movie.douban.com/top250?start='
data = bytes(urllib.parse.urlencode({"":""}),encoding='utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36' 
}
# 获取网页HTML源代码
urllib.request.urlopen(urllib.request.Request(url=url,data=data,headers=headers,method='POST')).read().decode('utf-8')


# 获取一个get请求
response = urlre.urlopen('http://www.baidu.com')
# 获取网页源代码
print(response.read().decode('utf-8'))

# response = re.urlopen('http://www.baidu.com')
# 网页状态 200
# print(response.status)
# 当我们访问网页时浏览器会向服务器发送请求头,里面包含浏览器版本等信息
# 如果我们的爬虫用get方式直接访问就会被有反爬机制的服务器识破我们的身份
# 因此我们需要用post方式发送请求,使用代理重新设置headers,并且通过urllib.parse模拟用户登录
# print(response.getheaders())
# print(response.getheader('Server'))

# 超时处理
# try:
    # response = re.urlopen('https://httpbin.org/get',timeout=0.5)
    # print(response.read().decode('utf-8'))

# except Exception as e:
#     print(e)
# 获取一个post请求,模拟用户登录时使用
# import urllib.parse
# data = bytes(urllib.parse.urlencode({"":""}),encoding='utf-8')
# response = re.urlopen('https://httpbin.org/post',data=data)
# print(response.read().decode('utf-8'))

url = 'https://movie.douban.com/top250?start='
data = bytes(urllib.parse.urlencode({"":""}),encoding='utf-8')
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'

}
req = re.Request(url=url,data=data,headers=headers,method='POST')
response = re.urlopen(req)
print(response.read().decode('utf-8'))

2.re(匹配HTML源代码)

# m = re.compile('aa').search('cab')
# m = re.search('aa','dadaa')     # 前面是规则,后面是校验对象
# <re.Match object; span=(3, 5), match='aa'>

m = re.findall('[a-c]','dkcfjsabaefaf')  # 找到所有匹配的项
# ['c', 'a', 'a', 'a']

m = re.sub('a','A','asdfgdada')     # 找到a,用A替换
# AsdfgdAdA

3.bs4(HTML/XML的解析器)

BeautifulSoup4将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象被归纳为4种:

  • Tag 标签及其内容(查找第一个符合要求的标签)
    对于 Tag,它有两个重要的属性,是 name 和 attrs
  • NavigableString string 标签内容
  • BeautifulSoup 整个文档
  • Comment 一个特殊类型的 NavigableString 对象,输出的内容不包括注释符号
搜索文档树

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

在上面的栗子中我们简单介绍了find_all的使用,接下来介绍一下find_all的更多用法-过滤器。这些过滤器贯穿整个搜索API,过滤器可以被用在tag的name中,节点的属性等。

  1. # 两者是相等的
  2. # t_list = bs.find_all("a") => t_list = bs("a")

传入参数:

  1. 字符串过滤:会查找与字符串完全匹配的内容

  2. 正则表达式过滤:如果传入的是正则表达式,那么BeautifulSoup4会通过search()来匹配内容

  3. 列表:如果传入一个列表,BeautifulSoup4将会与列表中的任一元素匹配到的节点返回

  4. 方法:传入一个方法,根据方法来匹配

CSS选择器

BeautifulSoup支持发部分的CSS选择器,在Tag获取BeautifulSoup对象的.select()方法中传入字符串参数,即可使用CSS选择器的语法找到Tag

通过标签名查找

print(bs.select('title'))

属性查找

print(bs.select('a[class="bri"]'))

更多见beautifulsoup菜鸟教程

4.xlwt(解析出的数据保存到Excel)

import xlwt                         		# 操作Excel
workbook = xlwt.Workbook(encoding='utf-8')  # 创建Excel工作表
worksheet = workbook.add_sheet('sheet1')    # 创建工作簿
worksheet.write(0,0,'hello')                # 在工作簿第一行第一列设置数据
workbook.save('student.xlsx')               # 命名并保存工作表

5.sqlite3(解析出的数据保存到sqlite数据库)


conn = sqlite3.connect('db.sqlite3')   # 打开或创建数据库文件

cursor = conn.cursor()					# 创建游标

# sql = '''
#     create table company(
#         id int primary key not null,
#         name text not null,
#         age int not null,
#         address char(20),
#         salary real
#     );
# '''

# sql = '''
#     insert into company values(1,'张三',10,'重庆',8888);
# '''
result = cursor.execute('select * from company')

for i in result:
    print('id=',i[0])
    print('id=',i[1])
    print('id=',i[2])
    print('id=',i[3])

# result = cursor.fetchall()
# print(result)
# conn.commit()
cursor.close() 
conn.close()

执行流程

在这里插入图片描述

# 通过urllib.request解析一个指定url内容,返回网页HTML源码
def askUrl(url):
    headers = {     # 模拟浏览器头部信息,发送给豆瓣服务器,一般网站有反爬机制,检测到爬虫禁止访问
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.96 Safari/537.36'
        # 用户代理,避免被发现是爬虫,告诉豆瓣浏览器我们是什么类型的机器(本质上是告诉浏览器我们可以接收什么水平的文件内容)
    }
    req = urlre.Request(url=url, headers=headers)
    try:
        response = urlre.urlopen(req)
        html = response.read().decode('utf-8')
        # print(html)
    except Exception as e:
        print(e)

    return html

# HTML源码中找到需要信息的标签,用正则模糊匹配
findLink = re.compile(r'<a href="(.*?)"') # 影片详情链接
findImgSrc = re.compile(r'<img.*src="(.*?)"',re.S) # 影片图片,re.S去掉换行符
......
# 找到子网页的地址规律,给askUrl解析每个子网页
# 通过bs4中的BeautifulSoup搜索每个子网页的文档树
# 循环遍历每个子网页,将信息保存在列表中,最后将列表保存在存放列表的列表中
def getData(baseurl):
    datalist = []
    for i in range(10):   # 获取页面信息十次
        url = baseurl + str(i*25)
        html = askUrl(url)  # 保存获取到的网页源码
        # 逐一解析数据
        soup = BeautifulSoup(html,'html.parser')
        for item in soup.find_all('div',class_='item'):    # 查找符合要求的字符串,形成列表
            # print(item)
            data = []   # 保存一部电影的所有信息
            item = str(item)

            # 七项信息,其中titles占两个位置,数组中每八位保存一部电影信息
            # 影片详情链接
            link = re.findall(findLink,item)[0]   # 查找指定字符串
            data.append(link)
  			.....
            data.append(bd.strip())     # 去掉前后的空格
            datalist.append(data)       # 将处理好的一部电影信息放入datalist
            # for i in data:
            #     print(i)
    print('数据爬取成功')
    return datalist
# 保存数据到excel
def saveData(dataList,savePath):
    workbook = xlwt.Workbook(encoding='utf-8')
    worksheet = workbook.add_sheet('sheet1')
    colTitle = ('电影详情链接', '图片链接', '影片中文名', '影片英文名', '影片评分', '评价人数', '影片概况', '相关信息')
    for i in range(8):
        worksheet.write(0, i, colTitle[i])
    for i in range(250):
        item = dataList[i]
        for j in range(8):
            data = item[j]
            worksheet.write(i + 1, j, data)

    workbook.save(savePath)
# 保存数据到sqlite数据库
def saveDataBase(dataList,savePath):

    conn = sqlite3.connect(savePath)  # 打开或创建数据库文件
    cur = conn.cursor()

    sqlCr = '''
        create table db_top250 if not exists(
            id int primary key autoincrement,
            link text,
            img text,
            cname varchar,
            ename varchar,
            rated int,
            judge int,
            inq text,
            bd text
        );
    '''
    cur.execute(sqlCr)

    for item in dataList:
        for i in range(len(item)):
            if i == 4 or i == 5:
                continue

            item[i] = '"'+item[i]+'"'
        sqlIn = '''
            insert into db_top250(link,img,cname,ename,rated,judge,inq,bd) values(%s)
        ''' % ','.join(item)  # 将,添加在每个item之间
        cur.execute(sqlIn)
        conn.commit()

    cur.close()
    conn.close()

爬取结果

在这里插入图片描述
在这里插入图片描述

数据可视化

Flask框架目录结构

在这里插入图片描述

词云

import jieba    # 分词
from matplotlib import pyplot as plt  # 绘图,数据可视化
from wordcloud import WordCloud     # 词云
from PIL import Image               # 图形处理
import numpy as np                  # 矩阵运算
import sqlite3                      # 数据库

# 准备词云所需的文本
con = sqlite3.connect('../../movie.db')
cur = con.cursor()
sql = 'select inq from db_top250'
data = cur.execute(sql)
text = ''
for item in data:
    text = text + item[0]
# print(text)
cur.close()
con.close()

# 分词
cut = jieba.cut(text)
print(cut)  # 生成器<generator object Tokenizer.cut at 0x0CA06A38>
string = ' '.join(cut)
# print(len(string))  # 5543

img = Image.open('../../tree.jpg')  # 打开遮罩图片
img_array = np.array(img)           # 将图片转化为数组
wc = WordCloud(
    background_color='white',
    mask=img_array,
    font_path='simfang.ttf'     # 禹卫书法行书简体.ttf
)
wc.generate_from_text(string)

# 绘制图片
fig = plt.figure(1)
plt.imshow(wc)
plt.axis('off')  # 坐标轴显示
# plt.show()

plt.savefig('../../word.jpg',dpi=500)

在这里插入图片描述

Echarts图表

Echarts官网

# 需要下载导入Echarts的js文件
<script src="../static/js/echarts.min.js"></script>

<script type="text/javascript">

       var myChart = echarts.init(document.getElementById('main-lb'));

       // 指定图表的配置项和数据
       option = {
      title:{
         text:'豆瓣评分'
      },
      color:['#3398DB'],
      tooltip: {
         trigger: 'axis',
         axisPointer: {            // 坐标轴指示器,坐标轴触发有效
            type: 'shadow'        // 默认为直线,可选为:'line' | 'shadow'
         }
      },
      grid: {
         left: '3%',
         right: '4%',
         bottom: '3%',
         containLabel: true
      },
      xAxis: [
         {
            type: 'category',
            data: {{ score|tojson }}
                       // ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
            /*axisTick: {
               alignWithLabel: true
            }*/
         }
      ],
      yAxis: [
         {
            type: 'value'
         }
      ],
      series: [
         {
            name: 'score',
            type: 'bar',
            barWidth: '60%',
            data: {{count}}
                   // [10, 52, 200, 334, 390, 330, 220]
         }
      ]
   };

       // 使用刚指定的配置项和数据显示图表。
       myChart.setOption(option);


   </script>


   {
            type: 'value'
         }
      ],
      series: [
         {
            name: 'score',
            type: 'bar',
            barWidth: '60%',
            data: {{count}}
                   // [10, 52, 200, 334, 390, 330, 220]
         }
      ]
   };

       // 使用刚指定的配置项和数据显示图表。
       myChart.setOption(option);


   </script>

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

豆瓣Top250:Python爬虫+数据可视化 的相关文章

随机推荐

  • AD20-封装的创作及添加

    原理图你是可以画的大一点 丑一点 但是封装库一定要按一比一的比例去画 否者是会影响后期的制作 也有可能是不能做出来的 画原理图是在 这个文件中进行 Ctrl m 是测量中心距离 先选中一个中心 在选中另一个中心 gg 按两次 是设置栅格的长
  • 浅谈数组与链表的区别

    1 区别 1 数组元素地址需要连续内存空间 链表节点地址不需要连续内存空间 2 数组在最初就确定了成员数量 后期无法修改 链表的节点个数可动态增减 3 数组元素只能是同1种数据类型 链表节点可携带多种数据类型 4 数组从栈中分配空间 链表从
  • java元注解

    java元注解 本文涉及以下这些内容 如果不清楚的话 可以看一下 相信会对你有些许帮助 1 使用IntelliJ IDEA 2018查看字节码 2 使用IntelliJ IDEA 2018生成帮助文档 本文主要针对于java8 java8定
  • 第十四届蓝桥杯B组第一期模拟题

    1 十进制整数 2 在十进制中是 1 位数 在二进制中对应 10 是 2 位数 十进制整数 22 在十进制中是 2 位数 在二进制中对应 10110 是 5 位数 请问十进制整数 2022 在二进制中是几位数 include
  • Python响应式类库RxPy简介

    RxPy是非常流行的响应式框架Reactive X的Python版本 其实这些版本都是一样的 只不过是各个语言的实现不同而已 因此 如果学会了其中一种 那么使用其他的响应式版本也是轻而易举的 之前我就听说过这个框架 最近决定好好研究一下 基
  • Jmeter(三十六) - 从入门到精通进阶篇 - 设置负载阶梯式压测场景(详解教程)

    1 简介 在性能测试中 有时需要模拟一种实际生产中经常出现的情况 即 从某个值开始不断增加压力 直至达到某个值 然后持续运行一段时间 然后继续加压达到某个值持续运行 如此循环直到达到预期的峰值 运行一段时间 在jmeter中 有这样一个插件
  • SASS 中的占位符%,@extend,@mixin(@include)的使用场景

    SASS在线编译网站 https www sassmeister com 占位符 被声明为占位符的CSS类 不会出现在最终生成的CSS中 SASS代码 log display block color black log debug exte
  • SQL删除重复数据,保留ID最大的一条

    在数据库中可能会存在重复数据 需要删除并且保留其中一条 这里我们保留其中id最大的一条 DELETE FROM T Dat BankData WHERE BankCode IN SELECT BankCode FROM T Dat Bank
  • Idea在plugin的marketplace中一直查不到东西&安装插件

    1 问题出现 我在Intellij IDEA 2018中搜索安装我们想要的插件时 有时候发现打开Setting gt Plugins Marketplace搜索插件页面加载不出来 而且搜索插件也搜索不出来 2 原因分析 IDEA的模块系统加
  • 解决 Access denied for user'root'@'IP地址'

    解决mysql Access denied for user root IP地址 问题 在MYSQL 中 用远程软件登陆服务器 有时出现 Access denied for user root localhost www 2cto com
  • jQuery 入门教程(29): jQuery UI Datepicker 示例(二)

    显示月份和年份选择下拉框 changeMonth 和changeYear 选择可以打开和关闭月份和年份下拉选择框 1 2
  • 数码管原理

    今天有师弟问我数码管的问题 我想起我刚学单片机的时候 好像也在数码管的地方迷糊了一段时间 就简单写写数码管的原理 首先 什么是数码管 百度百科解答 数码管 也称作辉光管 是一种可以显示数字和其他信息的电子设备 玻璃管中包括一个金属丝网制成的
  • 多处理器的基本概念

    SISD 单指令流单数据流 特性 各指令序列只能并发 不能并行 每条指令处理一两个数据 不是 数据级并行技术 硬件组成 一个处理器 一个主存储器 若采用指令流水线 需设置多个功能部件 采用多模块交叉存储器 SIMD 单指令流多数据流 特性
  • 使用较广泛的安全测试工具有哪些?

    使用较广泛的安全测试工具有哪些 安全测试是一个非常复杂的过程 安全测试所使用到的工具也非常多 而且种类不一 如漏洞扫描工具 端口扫描工具 抓包工具 渗透工具等 一 Web漏洞扫描工具 AppScan AppScan是IBM公司开发的一款We
  • mysql未开启binlog恢复数据_MYSQL bin_log 开启及数据恢复

    参考博客 A https www jianshu com p 55b0d52edca2 B https www cnblogs com martinzhang p 3454358 html C https www cnblogs com x
  • C语言-从txt文件中读取数据,忽略换行及回车

    long file size char filename FILE fp fopen filename r if fp return 1 fseek fp 0L SEEK END long size ftell fp fclose fp r
  • Mysql安装,控制台安装

    控制台安装要比exe方式安装简单很多 下载mysql 官网地址 mysql 解压下载的文件后 在生成的主目录里面创建一个my ini文件 文件内容如下 mysqld 端口号 port 3306 mysql安装目录 basedir C Pro
  • 步进电机S型曲线加速的实现

    之前做电机相关的项目比较少 最近有个项目涉及到步进电机的精确控制 参考了一些资料研究了一下S型曲线加减速 这里总结一下分享给大家 硬件是 STM32 驱动器 步进电机 STM32定时器输出PWM 控制驱动器来驱动步进电机 单片机只要控制电机
  • ROS系统上的单目相机标定步骤

    单目相机标定步骤 前置条件 已经安装完usb cam包 Git链接 已经安装完camera calibration包 安装了完整的ROS系统就有 可以通过下面的命令来检查 rosdep install camera calibration
  • 豆瓣Top250:Python爬虫+数据可视化

    文章目录 前言 数据爬取 测试类库 1 urllib request 获取网页HTML源代码 2 re 匹配HTML源代码 3 bs4 HTML XML的解析器 搜索文档树 CSS选择器 4 xlwt 解析出的数据保存到Excel 5 sq