微信公众号-脚本简单实现,自动新建草稿并发布草稿文章,代码开源

介绍

本来想写一个自动化发布微信公众号的小绿书的脚本。但是微信公众号官网没有小绿书的接口。

想着算了吧,写都写了,那就写一个微信普通文章的脚本吧。

写完了 就想着把脚本分享出来,给大家一起交流下。

水平有限,大佬轻喷。

 

思路

1,获取百度热搜列表

2,给热搜图片加上文字标题

3,上传图片到微信公众号素材库

4,新建微信公众号草稿

5,发布草稿

 

前期准备

1,注册微信公众号,获取AppID和AppSecret

 

2,微信公众号接口文档( 文档链接),参照文档进行接口调用

3,微信公众号设置IP白名单

在服务器上面获取出口外网ip

curl -s https://ipinfo.io/ip

 

环境要求

1,我使用的是python12

2,依赖就需要安装PIL库,其他库都是默认安装的

(py12-ai-django5) [root@gtp-test01-cyt wxmp]# python -V

Python 3.12.4


#
import requests
import os
import time
import yaml
import json
import string

from PIL import Image, ImageDraw, ImageFont
 
# 安装PIL
pip install pillow==10.4.0
 
# 运行脚本wxmp.py 就行
python wxmp.py
 
# 输出

图片已保存到 hotimg/orgimg/2.png
图片已保存到 hotimg/orgimg/3.png
图片已保存到 hotimg/orgimg/4.png
图片已保存到 hotimg/orgimg/5.png
图片已保存到 hotimg/orgimg/6.jpg
图片已保存到 hotimg/orgimg/7.jpg
图片已保存到 hotimg/orgimg/8.png
图片已保存到 hotimg/orgimg/9.png
图片已保存到 hotimg/orgimg/10.jpg
图片已保存到 hotimg/orgimg/11.png
图片已加文字 hotimg/nowimg/2.png
图片已加文字 hotimg/nowimg/3.png
图片已加文字 hotimg/nowimg/4.png
图片已加文字 hotimg/nowimg/5.png
图片已加文字 hotimg/nowimg/6.jpg
图片已加文字 hotimg/nowimg/7.jpg
图片已加文字 hotimg/nowimg/8.png
图片已加文字 hotimg/nowimg/9.png
图片已加文字 hotimg/nowimg/10.jpg
图片已加文字 hotimg/nowimg/11.png
新建草稿成功--{'media_id': 'V4QdIouS1e-m5FaD0_0keQQMcEMKo0-3YjLoF_JqJohqywWC3Byyr81SXUi1TheO', 'item': []}
{'errcode': 0, 'errmsg': 'ok', 'publish_id': 2247483801, 'msg_data_id': 2247483801}

 

 

 

 获取接口token

1,由于access_token的有效期只有2小时,故需要定时刷新。

2,这里使用app_token.yaml来保存获取到的token以及时间;token在时效内返回保存的token,超过时效会获取新的token

def get_token(app_id='',  # 微信公众号AppIDapp_secret=''  # 微信公众号AppSecret
):"""获取token:return:"""url = f'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={app_id}&secret={app_secret}'res = requests.get(url=url)result = res.json()if result.get('access_token'):token = result['access_token']print(f"获取token成功:{token[:14]}****")return tokenelse:print(f"获取token失败--{result}")def refresh_token():"""token刷新机制:return:"""app_token_path = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'app_token.yaml'try:# 读取时间和tokenif not os.path.exists(app_token_path):with open(app_token_path, 'w+') as f:f.write('')cfg_token = yaml_read(app_token_path)t = cfg_token['time']record_token = cfg_token['token']cur_time = time.time()# token时间在7200s之内,返回tokenif 0 < cur_time - t < 7200:# print(f"token时效内")return record_token# token过期,刷新时间和tokenelse:# print('token已过期')token = get_token()if token:data = {'time': time.time(), 'token': token}yaml_clear(app_token_path)yaml_write(data, app_token_path)return tokenexcept TypeError:# 获取初始时间和tokenprint('获取初始token')token = get_token()data = {'time': time.time(), 'token': token}yaml_write(data, app_token_path)return tokendef yaml_read(file):"""yaml文件读取:param file::return:"""with open(file=file, mode="r", encoding="utf-8") as f:data = yaml.safe_load(f.read())return datadef yaml_write(data, file):"""yaml文件写入:param data::param file::return:"""with open(file, 'a', encoding='utf-8') as f:yaml.dump(data,stream=f,allow_unicode=True,  # 避免unicode编码问题sort_keys=False  # 不自动排序
        )def yaml_clear(file):"""yaml文件清空:param file::return:"""with open(file, 'w', encoding='utf-8') as f:f.truncate()

 

获取热搜

这里我是找的网上别人写好的接口。简单快速方便

https://dabenshi.cn/other/api/hot.php?type=douyinhot // 抖音热点
https://dabenshi.cn/other/api/hot.php?type=toutiaoHot // 头条热榜
https://dabenshi.cn/other/api/hot.php?type=baidu // 百度热搜

我这里使用的是百度热搜。

 

获取热搜数据

# 获取热搜数据
def get_hotdata():'''获取百度热搜的数据url网上找的: https://dabenshi.cn/other/api/hot.php?type=baidu'''url = f"https://dabenshi.cn/other/api/hot.php?type=baidu"hotdata = [] # 存储所有的热搜数据
res = requests.get(url=url)result = res.json()hotdata = result['data'][1:11]    # 这里我只拿了10条数据


# 数据就是一个打列表,里面有字典
hotdata =[
        {"index": 2,"title": "外交部回应是否邀请特朗普访华","desc": "1月21日,外交部就“中方是否邀请特朗普访华”一事做出回应:愿同美国新政府保持沟通,加强合作。","pic": "https:\/\/fyb-2.cdn.bcebos.com\/hotboard_image\/4d0700b48e6c791e29f1e231e24af061","url": "https:\/\/www.baidu.com\/s?wd=%E5%A4%96%E4%BA%A4%E9%83%A8%E5%9B%9E%E5%BA%94%E6%98%AF%E5%90%A6%E9%82%80%E8%AF%B7%E7%89%B9%E6%9C%97%E6%99%AE%E8%AE%BF%E5%8D%8E&sa=fyb_news&rsv_dl=fyb_news","hot": "797.6万","mobilUrl": "https:\/\/www.baidu.com\/s?wd=%E5%A4%96%E4%BA%A4%E9%83%A8%E5%9B%9E%E5%BA%94%E6%98%AF%E5%90%A6%E9%82%80%E8%AF%B7%E7%89%B9%E6%9C%97%E6%99%AE%E8%AE%BF%E5%8D%8E&sa=fyb_news&rsv_dl=fyb_news"}
]

 

下载热搜图片

其实就是把热搜数据里面的pic图片保存到了本地

这样一会就好给图片加上标题文字了

def get_hotimg(hotdataall):"""下载热搜图片hotdata: 所有数据"""if hotdataall:for hotdata in hotdataall:try:# 发送HTTP GET请求获取图片数据response = requests.get(hotdata['pic'], timeout=10)# 检查请求是否成功if response.status_code == 200:# 获取Content-Type头信息content_type = response.headers.get('Content-Type')# 根据Content-Type判断图片类型image_extension = Noneif content_type == 'image/jpeg':image_extension = '.jpg'elif content_type == 'image/png':image_extension = '.png'elif content_type == 'image/gif':image_extension = '.gif'else:raise Exception(f"Unsupported image type: {content_type}")# 以二进制写模式打开文件,并将图片数据写入文件img_name = "hotimg/orgimg/" + str(hotdata['index']) + image_extensionimg_name_new = "hotimg/nowimg/" + str(hotdata['index']) + image_extensionwith open(img_name, 'wb') as file:file.write(response.content)print(f'图片已保存到 {img_name}')hotdata['image_path'] = img_namehotdata['image_path_new'] = img_name_newelse:print(f'下载图片失败,状态码: {response.status_code}')except requests.RequestException as e:print(f'请求出现异常: {e}')

 

给图片加上标题文字

# 给图片加上文字if hotdata:for hotdata_in in hotdata:image_path = hotdata_in['image_path']image_path_new = hotdata_in['image_path_new']text = hotdata_in['title']max_width = 500add_text_to_image(image_path, image_path_new, text=text, max_width=max_width)
def add_text_to_image(image_path, image_path_new, text='', max_width=500):'''给图片添加文字'''image = Image.open(image_path)draw = ImageDraw.Draw(image)width, height = image.sizefont_size = max(30, int(width * 0.03))font = ImageFont.truetype("ttf/feihuasongti.ttf", font_size)text_color = (255, 255, 255)  # 黑色字体shadow_color = (0, 0, 0)  # 黑色阴影# text_width, text_height = draw.textsize(text, font=font)# 获取文本尺寸bbox = draw.textbbox((0, 0), text, font=font)text_width = bbox[2] - bbox[0]text_height = bbox[3] - bbox[1]while text_width > width - 30:font_size -= 1font = ImageFont.truetype("ttf/feihuasongti.ttf", font_size)# text_width, text_height = draw.textsize(text, font=font)# 获取文本尺寸bbox = draw.textbbox((0, 0), text, font=font)text_width = bbox[2] - bbox[0]text_height = bbox[3] - bbox[1]# 计算文本位置x = width - text_widthy = height - text_height - 30# 绘制文本阴影draw.text(((x/2) + 2, y + 2), text, font=font, fill=shadow_color)draw.text((x / 2, y), text, font=font, fill=text_color)image.save(image_path_new)print(f'图片已加文字 {image_path_new}')

类似这样,在图片底部加上文字

 

上传图片素材

这块会返回上传到素材url。这个url地址,可以在文章里面使用

def add_media(hotdataall):"""新增临时素材: https://api.weixin.qq.com/cgi-bin/media/upload?access_token=ACCESS_TOKEN&type=TYPE上传图文消息内的图片获取URL, 新增永久素材: https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN新增其他类型永久素材, 新增永久素材: https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE"""# url = f"https://api.weixin.qq.com/cgi-bin/media/upload?access_token={refresh_token()}&type=image"url = f"https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token={refresh_token()}"if hotdataall:for hotdata in hotdataall:with open(hotdata['image_path_new'], 'rb') as fp:files = {'media': fp}res = requests.post(url, files=files)res = json.loads(str(res.content, 'utf8'))hotdata["wx_img_url"] = res['url']

 

新建草稿

这里会返回草稿的ID

def add_draft(hotdataall):'''新建草稿'''url = f'https://api.weixin.qq.com/cgi-bin/draft/add?access_token={refresh_token()}'# content = "<img src='https://mmbiz.qpic.cn/sz_mmbiz_jpg/hY63os7Ee2Ro6WVkfj9nvfDdpONqLwr48J2eQEYXygs3cWibLvQTHAveYWNnXOOWHO3jZldO3fr7quVj6V0X5uA/0?wx_fmt=jpeg'/>"# 读取文件html# 打开HTML文件并读取内容with open('content.html', 'r', encoding='utf-8') as file:html_content_template = file.read()# 动态生成草稿content内容全部,先定义一个变量html_content = ""# 动态生成草稿content内容片段for hotdata in hotdataall:# 判断热搜第一if hotdata['index'] == 2:title_color = "red"else:title_color = "black"# 定义变量hot_context = {'num': hotdata['index'] - 1,'url_img': hotdata['wx_img_url'],'title_color': title_color,'title_title': hotdata['title'],'describe': hotdata['desc'],}# 替换变量substitute_data = string.Template(html_content_template)result = substitute_data.safe_substitute(hot_context)html_content += resultdata = {"articles": [{"title":"标题","author":"作者","digest":"描述","content":html_content,"thumb_media_id":"封面素材ID","need_open_comment":1,"only_fans_can_comment":1}]}res = requests.post(url=url, data=json.dumps(data, ensure_ascii=False).encode('utf-8'))if res.status_code == 200:result = json.loads(res.content)if result.get('media_id'):print(f'新建草稿成功--{result}')return result['media_id']else:print(f'新建草稿失败--{result}')else:print(f'新建草稿失败--{res.text}')

 

发布草稿

def free_publish(media_id):'''发布草稿'''url = f'https://api.weixin.qq.com/cgi-bin/freepublish/submit?access_token={refresh_token()}'data = {"media_id": media_id}res = requests.post(url=url, json=data)res = json.loads(str(res.content, 'utf8'))print(res)

 

源码

gitee:https://gitee.com/ccsang/wxmp

 

关注我的公众号

这个公众号的文章就是这个脚本定时发送的。

希望这个脚本对你有用。欢迎交流

最近想弄些PRA,自动化弄下那些没有接口的应用的。有大佬指教吗。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/872871.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何在织梦CMS中修改网站标题?

织梦CMS(DedeCMS)是一款流行的开源内容管理系统。以下是修改织梦网站标题的步骤:登录后台:使用管理员账号登录织梦CMS后台管理系统。 进入模板管理:在后台管理系统中找到“模板管理”或“模板文件管理”选项。 编辑模板文件:找到包含网站标题的模板文件(如index.htm),…

修改公司网站数据库名称时需要注意的问题及解决方案

问题描述 当需要对公司网站的数据库名称进行更改时,有哪些潜在风险和挑战?如何确保这一过程顺利进行? 答案 修改公司网站的数据库名称是一项敏感的操作,因为它涉及到整个系统的底层架构,稍有不慎就可能导致数据丢失或服务中断。以下是需要注意的问题及解决方案:评估影响范…

使用FlashFXP修改网站代码

问题描述 如何使用FlashFXP工具安全地修改网站代码,确保网站正常运行? 答案 FlashFXP是一款常用的FTP客户端,广泛用于网站文件的上传和下载。通过FlashFXP,用户可以方便地修改网站代码。以下是详细的步骤和注意事项:安装FlashFXP:首先,下载并安装FlashFXP软件。确保安装…

如何处理虚拟主机上的系统误报和非法信息检测问题?

要处理虚拟主机上的系统误报和非法信息检测问题,您可以采取以下措施:确认误报文件:检查被误报为病毒的文件是否确实为正常文件。如果是正常文件,建议联系程序提供商重新设计页面,避免使用容易被误判的文件名或格式。 如果文件确实是合法的,可以尝试将其路径添加到白名单中…

服务器端口不通?快速排查与解决方法

用户在配置安全组时遇到问题,尽管已经开放了特定端口(如1238和8283),但仍然无法访问这些端口。例如,用户尝试访问这两个端口时发现ping不通。 解决方案:步骤 描述1 确认服务器上是否有服务正在监听这些端口。如果没有服务监听,则外网无法访问这些端口。2 检查服务器防火…

FTP修改网站内容后无变化的原因分析及解决方案

当通过FTP修改网站内容后无变化时,可能是由多种原因引起的。以下是详细的排查步骤和解决方案:确认FTP登录信息:确保您使用的FTP用户名和密码是正确的,并且连接的是正确的服务器地址。建议使用ftp://127.0.0.1重新登录FTP,确保连接无误。检查文件上传路径:确认上传的文件是…

spring综合性利用工具-SpringBoot-Scan(一),附下载链接。

日常渗透过程中,经常会碰到Spring Boot搭建的微服务,于是就想做一个针对Spring Boot的开源渗透框架,主要用作扫描Spring Boot的敏感信息泄露端点,并可以直接测试Spring的相关高危漏洞。 于是,就写了这么一个工具:SpringBoot-Scan 【简称:“SB-Scan”(错乱】 1、工具下载…

VLAN聚合技术:Super-vlan

Super-VLAN,也称为VLAN聚合(VLAN Aggregation),是一种网络配置技术,主要用于优化IP地址资源的利用和隔离广播域。 一、定义与功能 Super-VLAN是通过将多个VLAN(称为Sub-VLAN)聚合成一个逻辑的VLAN(即Super-VLAN)来实现的。这些Sub-VLAN使用同一个IP子网和缺省网关,从…

heapdump敏感信息提取工具-JDumpSpider(一) ,附下载链接

​ 介绍 HeapDump敏感信息提取工具 在日常得渗透测试工作中,经常遇到spring actuator未授权漏洞,而且在实际过程中也常常会下载到heapdump这个文件。了解过这个文件的人知道,Heap Dump也叫堆转储文件,是一个Java进程在某个时间点上的内存快照。Heap Dump是有着多种类型的。…

LCR 091. 粉刷房子

题目思路描述 动态规划状态定义:costs[i][j] 表示第 i 个房子粉刷成第 j 种颜色的花费。 dp[i][j] 表示前 i 个房子粉刷到第 i 个房子为第 j 种颜色的最小花费。状态转移方程:dp[i][j] = costs[i][j] + min(dp[i-1][k]),其中 k != j。 即当前房子的颜色不能与前一个房子的颜…

代码的可测试性

目录单元测试可测试接口面向接口单元测试 一个代码质量和工程质量有保证的项目一定有比较合理的单元测试覆盖率,没有单元测试的项目一定是不合格的或者不重要的,单元测试应该是所有项目都必须有的代码,每一个单元测试都表示一个可能发生的情况,单元测试就是业务逻辑。可测试…

一镜到底,通过Llama大模型架构图看透transformers原理

想了解大模型 Llama 的工作原理?Llama Nuts and Bolts 项目不依赖外部库,通过 Go 语言从零构建 Llama 3.1 8B-Instruct 模型,为学习者提供了一个教育性深度探索,让您动手实践理解大型语言模型。一镜到底,通过Llama大模型架构图看透transformers原理 Llama Nuts and Bolts是…