GitHub | 您所在的位置:网站首页 › 热搜怎么做数据 › GitHub |
当你想要跟踪微博的热门话题时,通过编写一个Python爬虫,来获取微博热搜榜单上的实时数据,并将其可视化展示出来,通过邮件或QQ机器人将其推送,亦可以将其存档,用以保留不同时期的舆论热点。
此外,排行榜项目一向是学习Python爬虫时必备的练手项目,通过本项目,可以学习如何轻松制作仿微博热搜结果的图片、学习基础的代码能力以及相关的数据可视化,数据推送等多方面知识。
此外,还有更多的进阶思路,在此处抛砖引玉: 使用selenium库无头浏览器进行截图,获取原生热榜截图 引入邮件库,定期向邮箱中推送爬取的结果 部署到服务器或设置定时任务,整理微博热搜库到Excel或其他存储结构 获取某一时间段的热搜并生成词云进行分析 使用nonebot库将其制作为QQ/社交软件机器人插件 项目实现 数据获取在对一个网站或网页进行爬虫时,选择正确的方法往往能够事半功倍,因此观察网站结构和网站提供的各种API就非常重要,下面我们将举例对不用方法进行分析。 直接从网页上抓取顾名思义,该方法就是通过直接分析网页页面,抓取到网页内容。 例如在本例中,可以获取到热搜本页的html页面,获取其 元素这是一种通用的,直观的爬虫方式,但存在几个问题。 需要伪装请求头,特别是cookie,否则返回的页面为空 cookie一旦过期,需要重新获取,或者根据cookie内容的规律设置变量 获取内容时比较复杂因此笔者一直强调在爬取页面时先要多观察,找到数据接口比直接爬取页面来说要方便的多。 从数据接口抓取微博开放平台提供了众多接口,微博热搜拥有自己的API接口,其url为:https://weibo.com/ajax/side/hotSearch
这样,我们就得到了微博热搜的数据文件。 数据解析 基础代码json文件是非常好的数据载体,它可以作为字典格式进行数据的读取。 我们在得到数据源后,就可以开始着手进行解析。 我们写一个main()函数,并调用hot_search()函数获取数据源 def main(num): data = hot_search() if not data: print('获取微博热搜榜失败') return print(f"置顶:{data['hotgov']['word'].strip('#')}") for i, rs in enumerate(data['realtime'][:num], 1): title = rs['word'] try: label = rs['label_name'] if label in ['新','爆','沸']: label = label else: label = '' except: label = '' print(f"{i}. {title} {label}") if __name__ == '__main__': num = 20 #获取热搜的数量 main(num)由于置顶热搜与普通热搜有所不同,我们先读取置顶热搜。
后面通过遍历即可获得每一条热搜的信息,其中变量num代表获取热搜的数量,可以传递参数控制。
运行后如图所示:
可以看到,我们已经成功的实现了解析的功能,将热搜解析为文本,并选取了标题和热度标签两个主要内容。
当然,也可以提取"raw_hot" 键中对应的热度,即热搜榜中的搜索热度。
加上这个数据后,结果又缺少了什么,没错,是时间,微博热搜都是具有时效性的,所以我们应该为其加入时间显示。 from datetime import datetime print(datetime.now().strftime('微博热搜榜 20%y年%m月%d日 %H:%M'))加入上述代码后,运行结果如下:
运行后结果如图:
在上面的基础代码中,我们已经实现了获取微博热搜的文字信息,如果我们想要更直观的,更友好的展示界面,就需要对其进行可视化,在本例中我们将其生成为如下的图片来进行展示。 由于我们绘图的基础是本文前一部分的代码内容,我们只需要新增一个函数来实现绘图功能,并不影响基础代码。 这也是程序中非常重要的模块化思想,同样的还有面向对象中的封装,都是为了便于后期对功能的增加和更改。 下面是基础代码部分,我们只去掉了部分输出,并为函数增加了返回值。 import requests from datetime import datetime def hot_search(): url = 'https://weibo.com/ajax/side/hotSearch' response = requests.get(url) if response.status_code != 200: return None return response.json()['data'] def decoding(num): data = hot_search() if not data: print('获取微博热搜榜失败') return top = (f"置顶:{data['hotgov']['word'].strip('#')}") hot_li = [] hot_label = [] for i, rs in enumerate(data['realtime'][:num], 1): title = rs['word'] try: label = rs['label_name'] if label in ['新','爆','沸']: label = label else: label = '' except: label = '' # hot_li.append(f"{i}. {title} {label}") hot_li.append(f"{title}") hot_label.append(f"{label}") return hot_li,hot_label接下来就是我们的主程序,对结果进行绘图 首先我们需要引入PIL库进行绘图。 from PIL import Image, ImageDraw, ImageFontPIL绘图的原理先创建一个指定的画板,然后通过对坐标轴X和Y轴的调整实现内容的布局。
我们的思路是首先创建一个与微博热搜图片等宽的白色幕布,然后为每行内容分配50像素的高度,根据获取的热搜数量计算出幕布的高度。
接下来我们需要将文字绘制到图片上,这部分的难点主要是文字布局。 在对文字布局调整前,我们首先应该对字体进行配置,否则无法绘制。 line_height = 50 # 每行文字高度 num_lines = len(li) # 总行数 font_size = 30 # 字体大小 text_color = (0, 0, 0) # 文本颜色 background_color = (255, 255, 255) # 背景颜色 separator_color = (200, 200, 200) # 分隔符颜色 separator_height = 1 # 分隔符高度 image_height = num_lines * line_height # 图像高度 # 字体配置 draw = ImageDraw.Draw(background) font = ImageFont.truetype("resource/heiti.ttf", font_size) num_font = ImageFont.truetype("resource/SmileySans.ttf", font_size)配置字体文件时需要提前将对应的字体ttf或者ttc文件放置于资源文件中,我选择黑体作为热搜标题字体,得意黑为编号与标签的字体,并对颜色和字体进行配置。
每一行的编号和文本只需要调整x轴的位置,就可以调整左右方向的位置,例如将编号固定在左侧35像素的位置,标题文本从135像素开始,是不是有种熟悉的感觉?就是CSS中left:130px的效果,或者padding-left:35px。 以下是绘图的完整代码: #!/usr/bin/env python # -*- coding: UTF-8 -*- ''' @Project :Project Achive @File :image.py @IDE :PyCharm @Author :lingxiaotian @Date :2023/9/5 15:54 ''' import requests from datetime import datetime from PIL import Image, ImageDraw, ImageFont def hot_search(): url = 'https://weibo.com/ajax/side/hotSearch' response = requests.get(url) if response.status_code != 200: return None return response.json()['data'] def decoding(num): data = hot_search() if not data: print('获取微博热搜榜失败') return top = (f"置顶:{data['hotgov']['word'].strip('#')}") hot_li = [] hot_label = [] for i, rs in enumerate(data['realtime'][:num], 1): title = rs['word'] try: label = rs['label_name'] if label in ['新', '爆', '沸']: label = label else: label = '' except: label = '' # hot_li.append(f"{i}. {title} {label}") hot_li.append(f"{title}") hot_label.append(f"{label}") return hot_li, hot_label def img(li, label): # 创建图像 width = 750 height = 350 + 70 + len(li) * 52 background = Image.new('RGB', (width, height), color=(255, 255, 255)) # 添加背景图片(如果需要替代顶部像素的背景) background_image = Image.open('resource/hot_research.jpg') # 替换为你的背景图片 background.paste(background_image, (0, 0)) line_height = 50 # 每行文字高度 num_lines = len(li) # 总行数 font_size = 30 # 字体大小 text_color = (0, 0, 0) # 文本颜色 background_color = (255, 255, 255) # 背景颜色 separator_color = (200, 200, 200) # 分隔符颜色 separator_height = 1 # 分隔符高度 image_height = num_lines * line_height # 图像高度 # 字体配置 draw = ImageDraw.Draw(background) font = ImageFont.truetype("resource/heiti.ttf", font_size) num_font = ImageFont.truetype("resource/SmileySans.ttf", font_size) # 生成文本列表 lines = li # 获取当前时间 time = datetime.now().strftime('20%y年 %m月 %d日 %H:%M %A') time_name = datetime.now().strftime('20%y年%m月%d日%H:%M') draw.text((130, 360), str(time), fill=(101, 109, 118), font=font, font_size=24) draw.rectangle([(0, 400), (width, 400 + separator_height)], fill=separator_color) # 逐行绘制文本和分隔符 y = 420 i = 1 for line in lines: # 绘制编号 draw.text((35, y - 3), str(i), fill=(255, 0, 0), font=num_font) # 绘制文本 draw.text((130, y), line, fill=text_color, font=font) # 绘制热度 draw.text((680, y - 3), label[i - 1], fill=(255, 0, 0), font=num_font) y += line_height i += 1 # 绘制分隔符 draw.rectangle([(0, y - 10), (width, y - 10 + separator_height)], fill=separator_color) y += separator_height # 保存图像 try: background.save(f"archive/{time_name}.png") print("保存成功!") except: print("保存失败!!!") if __name__ == "__main__": num = 20 # 获取热搜数 hot_li = decoding(num)[0] hot_label = decoding(num)[1] img(hot_li, hot_label) 3.2. selenium无头浏览器截图相比于直接绘图,直接截图无疑是一种更加简单快捷的方法,而且能够实现原生的微博热搜的效果,操作也十分简单,那么手动截图的话我们固然会,但如何使用selenium进行截图就是本项目中的重点。
什么是selenium?
selenium是Pyhton爬虫中非常重要的一种方式,由于selenium是使用真实的浏览器来进行访问,因此可以绕过很多反爬措施,其次,selenium可以控制浏览器对网页内容进行点击,滚动,输入等多种操作,例如输入账号密码和验证码并登录,滚动屏幕获取ajax内容。
下面是一个直观的演示:
****设置好后我们直接访问热搜榜url,并进行截图即可完成。 注意:由于打开网页后需要一定时间才会完全显示界面,因此设置了10秒钟的休眠,可以根据自己设备和网络情况具体调整时间。 # 导航到要截图的页面 url = 'https://s.weibo.com/top/summary?cate=realtimehot' driver.get(url) # 截取整个页面 print("正在运行,请稍后……") # time.sleep(10) screenshot = driver.get_screenshot_as_file(f'screenshot/{name}.png') # 关闭浏览器 driver.quit() print("运行完毕,请于文件夹中查看")当然,直接截图的话不会完整,可以通过滚动窗口,截屏后将所有图片拼接,获取长截图。 要启动无头模式,可以直接在配置中加入opts.add_argument('--headless') 即可。 总结在本项目中,我们探讨了如何使用30行不到的代码创建一个微博热搜爬虫,意图强调的是爬虫方式的选择的重要性,并提出了一些拓展思路。 同样的使用selenium无头模式也可以通过不到30行代码实现对热榜的爬取,但仅有图片信息,难以对数据进行固化和分析,所以说不同的爬虫方式有不同的特点,而选择适合需求的方法至关重要。 |
CopyRight 2018-2019 实验室设备网 版权所有 |