Python+MySQL+云服务器 定时爬取B站日榜与微博热搜榜信息并保存至数据库

原文链接

前言:

几乎所有主流信息网站/平台都有各自平台的榜单,这份榜单显示了网站在本日或一段时间以来的重要事件或突出内容。通过这份榜单可以获取这个网站的主流信息,以及诸多重要内容,一些大平台或主流应用的榜单甚至可以显示当前社会的某些现状与问题。

例如,通过微博热搜榜可以获取时下处于热点的时事新闻或娱乐花边。通过B站日榜可以获取当下年轻人爱好以及关注点,通过豆瓣榜单可以了解到大众对于书籍影视等产品类型的关注程度与喜好方向。这其中,前两者时限性很强,热搜榜每分钟进行一次更新,B站日榜每天进行更新

因此,如何获取这份榜单,并且持续高效的保存其中内容就显得十分具有现实意义。一天的榜单或许不能显示太多的信息,但大量的数据往往能展示出一定的规律性,也就具有了研究价值

流程

  1. 准备阶段
    • 云数据库的使用
    • 云服务器的使用
  2. 代码实现阶段
    • 利用python(bs4+pymysql+schedule)实现爬虫部分
    • SQL代码实现数据库创建
  3. 部署阶段
    • 云服务器选择
    • 数据库与服务器本地连接
    • SCREEN

准备阶段

云数据库

云数据库的好处主要在于方便简单,可以任意访问,并且使用云数据库可以避免爬取数据量过大时对自身电脑的影响

这里我选择购买的是腾讯云的MySQL基础班数据库,学生阶段还有很大的优惠
在这里插入图片描述

进入控制台后,选择管理就可以启动外网地址,这样我们就可以直接在本地连接到腾讯云数据库
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yhktcNDB-1588085763959)(http://47.97.124.78:8000/wp-content/uploads/2020/04/控制台.png)]

在这里插入图片描述

获得了外网地址并且设置了用户名与密码后,就可以在本地直接连接已购买的云数据库了,这里采用了navicat连接云数据库,navicat在连接选项中直接包括了腾讯云的MySQL数据库,直接点击,然后选择SSH连接,在准确输入各项信息,就可以成功连接到云数据库中,非常的简单便利

在这里插入图片描述

登录

云服务器

综合尝试了市面上常见的几款云服务器的基础班,阿里的阿里云,腾讯的腾讯云,亚马逊的AWS,以及谷歌的谷歌云,综合比较下来,由于我们要实现的功能比较简单,所以以上几款云服务器的基础版完全都可以实现,其中相对配置较复杂的是亚马逊(也可能是我选择的服务器问题)

代码实现阶段

代码实现主要分为两部分,首先是爬虫部分如何从微博与B站获取信息,以及获取到信息后如何进行数据清洗。其次是数据库与表格的创建

利用python实现爬虫部分

爬虫部分用到了bs4来解析网页,由于微博对热搜榜内容基本未作任何处理,所以很好获取

# 爬取微博热搜榜
def getHotNews():
    newsList=[]   # 存储热搜榜主要信息
    nums=[]
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}  # 伪装标头
    res=requests.get('https://s.weibo.com/top/summary',headers=headers)  # 请求网页
    soup = BeautifulSoup(res.text,'html.parser')  # 解析网页
    result=soup.find_all('td',class_='td-02')  # 找到目标信息,td-02是每个新闻主体的类标签
    num=0
    startTime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())  # 记录开始时间
    for i in result:
        num+=1
        content=i.find('a').text  # 事件内容
        try:
            attention=i.find('span').text  # 事件关注度
        except:
            attention=0
        nums.append([num,content,attention,startTime])  # 将有关信息添加至列表中
    return nums  # 返回信息列表
    

# 爬取微博实时榜
def getSocialNews():
    newsList=[]
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}
    res2=requests.get('https://s.weibo.com/top/summary?cate=socialevent',headers=headers)
    soup2 = BeautifulSoup(res2.text,'html.parser')
    result2=soup2.find_all('td',class_='td-02')
    num=0
    startTime=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    for i in result2:
        num+=1
        content=(i.find('a').text).strip('#')
        newsList.append([num,content,startTime])
    return newsList

B站日榜爬虫部分

# 爬取B站日榜新闻
def BilibiliNews():
    newsList=[]
    # 伪装标头
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}
    res=requests.get('https://www.bilibili.com/ranking/all/0/0/3',headers=headers) # 请求网页
    soup = BeautifulSoup(res.text,'html.parser')  # 解析网页
    result=soup.find_all(class_='rank-item')  # 找到榜单所在标签
    num=0
    startTime=time.strftime("%Y-%m-%d", time.localtime())  # 记录爬取的事件
    for i in result:
        try:
            num=int(i.find(class_='num').text)  # 当前排名
            con=i.find(class_='content')  
            title=con.find(class_='title').text  # 标题
            detail=con.find(class_='detail').find_all(class_='data-box')
            play=detail[0].text  # 播放量
            view=detail[1].text  # 弹幕量
            # 由于这两者存在类似15.5万的数据情况,所以为了保存方便将他们同义转换为整型
            if(play[-1]=='万'):
                play=int(float(play[:-1])*10000)
            if(view[-1]=='万'):
                view=int(float(view[:-1])*10000)
            # 以下为预防部分数据不显示的情况
            if(view=='--'):
                view=0
            if(play=='--'):
                play=0
            author=detail[2].text  # UP主

            url=con.find(class_='title')['href']  # 获取视频链接
            BV=re.findall(r'https://www.bilibili.com/video/(.*)', url)[0]  # 通过正则表达式解析得到视频的BV号
            pts=int(con.find(class_='pts').find('div').text)   # 视频综合得分
            newsList.append([num,title,author,play,view,BV,pts,startTime])  # 将数据插入列表中
        except:
            continue
    return newsList  # 返回数据信息列表

常见问题解决

在爬取信息过程中,出现了一部分难以处理的数据,就是B站的标题部分,在爬取到舞蹈区时出现了数据无法成功上传到数据库的情况,问题的原因就是标题内容中含有emoji表情字符。

解决方法有两种,一种是修改数据库的编码格式,适应emoji表情包即可,另一种就是在获取数据后,筛除掉数据中的表情包字符,由于表情包字符对于数据分析以及最后的结果几乎不构成影响,所以我这里采用了直接筛除表情包字符的方式来解决这个问题

筛除的方式也是多样的,可以利用正则表达式限定字符的范围,从而过滤掉表情包内容。一种比较简便的方式就是利用python中的emoji库,里边内置了一系列方法可以解决这个问题

title=con.find(class_='title').text  # 获取标题
title2=emoji.demojize(title)  # 转换emoji字符
title=re.sub(r':(.*?):','',title2).strip()  # 然后利用正则表达式删除这部分内容

MySQL部分-数据库创建与数据插入

关于数据库的创建,你可以选择直接定义在python中,再插入数据前自动创建表格,也可以选择先创建好表格,这样之后的方法中只需要定义如何插入数据

在这里插入图片描述

mysql> create table BILIBILI(
    -> NUM INT,
    -> TITLE CHAR(80),
    -> UP CHAR(20),
    -> VIEW INT,
    -> COMMENT INT,
    -> BV_NUMBER INT,
    -> SCORE INT,
    -> EXECUTION_TIME DATETIME);

将数据插入MySQL

def GetMessageInMySQL():
    # 连接数据库
    db = pymysql.connect(host="cdb-cdjhisi3hih.cd.tencentcdb.com",port=10056,user="root",password="xxxxxx",database="weixinNews",charset='utf8')
    cursor = db.cursor()  # 创建游标
    news=getHotNews()  # 调用getHotNews()方法获取热搜榜数据内容
    sql = "INSERT INTO WEIBO(NUMBER_SERIAL,TITLE, ATTENTION,EXECUTION_TIME) VALUES (%s,%s,%s,%s)"  # 插入语句
    timebegin=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())  # 记录开始事件,便于查找错误发生情况
    try:
        # 执行sql语句,executemany用于批量插入数据
        cursor.executemany(sql, news)
        # 提交到数据库执行
        db.commit()
        print(timebegin+"成功!")
    except :
        # 如果发生错误则回滚
        db.rollback()
        print(timebegin+"失败!")
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    db.close()

数据插入数据库过程失败常见原因

  • 数据类型不匹配
  • 数据大小超出规定限制
  • 插入语句不准确
  • 插入列表的问题

利用schedule实现定时爬取

# 记录程序运行事件
time1=time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
print("开始爬取信息,程序正常执行:"+time1)
# 每20分钟执行一次程序
schedule.every(20).minutes.do(startFunction) 
# 检查部署的情况,如果任务准备就绪,就开始执行任务
while True:
    schedule.run_pending()
    time.sleep(1)    

部署到云服务器阶段

由于榜单的时效性,所以我们必须不断获取数据,得到大量资料才有分析的价值。因此在自己个人电脑上运行程序就变得不现实,一方面,我们无法持续运行程序,电脑的开关机以及软件的关闭都会终止程序,我们需要时刻关注着代码进程才能及时重新运行软件。另一方面,持续在后台运行多个程序会占用电脑CPU,影响我们的日常使用

综上,将代码部署在云服务器上,是一种最优的解决方案,云服务器不会有关机的顾虑,代码可以持续运行不断爬取数据,云服务器还可以利用screen进行终端切换,完全不影响我们其他程序的正常运行


为了使程序的进行不影响云服务器的使用,而是独立运行,可以使用大部分Linux系统中都有的screen。

利用screen创建独立终端:

screen -S TEST  
# TEST是终端的名称

执行后会进入一个新的终端,我们可以直接在这个新终端中执行程序

python3 /usr/main.py

程序开始执行后,我们不需要再操作这个终端时,就可以按住CTRL+a+d退出该终端界面,退出终端后,如果向再次进入该终端可以通过screen -ls查看当前存在的终端列表

终端列表

然后通过以下命令就可以再次进入该终端中

screen -r 1602
# 1602就是要进入的终端编号

程序在终端中成功运行:

在这里插入图片描述

最终数据库效果

在这里插入图片描述

结语

因为部分内容是初步学习,所以不足之处肯定还有很多,也饶了很多弯路,花费时间最长的就是在服务器和数据库的配置过程上,各个平台内置软件并不相同,采用的系统或版本也出入很大,可以说做了很多无用功。不过最终得到的成功还是比较满意,也基本实现了初始设想的功能。

数据是基础,后续的分析过程是关键,只有不断了解深入,才能让获取到的数据展现出应有的功用与价值

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值