使用Python构建控制台应用,简单一点.主目的是抓取某个网站图片然后上传到素材.
流程
获取access token
首先需要知道自己的开发者AppID和开发者密码AppSecret.
然后获取access token
https请求方式: GET https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数 | 是否必须 | 说明 |
---|
grant_type | 是 | 获取access_token填写client_credential |
appid | 是 | 第三方用户唯一凭证 |
secret | 是 | 第三方用户唯一凭证密钥,即appsecret |
返回说明
正常情况下,微信会返回下述 JSON 数据包给公众号:1
| {"access_token":"ACCESS_TOKEN","expires_in":7200}
|
错误时微信会返回错误码等信息,JSON数据包示例如下(该示例为 AppID 无效错误):1
| {"errcode":40013,"errmsg":"invalid appid"}
|
素材管理
新增永久素材
对于常用的素材,开发者可通过本接口上传到微信服务器,永久使用。新增的永久素材也可以在公众平台官网素材管理模块中查询管理。
通过 POST 表单来调用接口,表单 id 为media,包含需要上传的素材内容,有filename、filelength、content-type等信息。
请注意:图片素材将进入公众平台官网素材管理模块中的默认分组。也就是说现在还不支持上传素材时创建分组.不过问题不大,到时候写文章时手动
http请求方式: POST,需使用https https://api.weixin.qq.com/cgi-bin/material/add_material?access_token=ACCESS_TOKEN&type=TYPE
参数 | 是否必须 | 说明 |
---|
access_token | 是 | 调用接口凭证 |
type | 是 | 媒体文件类型,分别有图片(image)、语音(voice)、视频(video)和缩略图(thumb) |
media | 是 | form-data中媒体文件标识,有filename、filelength、content-type等信息 |
新增永久视频素材需特别注意
在上传视频素材时需要 POST 另一个表单,id为description,包含素材的描述信息,内容格式为JSON,格式如下:1 2 3 4
| { "title":VIDEO_TITLE, "introduction":INTRODUCTION }
|
参数 | 是否必须 | 说明 |
---|
title | 是 | 视频素材的标题 |
introduction | 是 | 视频素材的描述 |
返回说明1 2 3 4
| { "media_id":MEDIA_ID, "url":URL }
|
获取素材总数
永久素材的总数,也会计算公众平台官网素材管理中的素材 2.图片和图文消息素材(包括单图文和多图文)的总数上限为100000,其他素材的总数上限为1000 3.调用该接口需 https 协议
接口调用请求说明
http请求方式: GET https://api.weixin.qq.com/cgi-bin/material/get_materialcount?access_token=ACCESS_TOKEN
使用库
requests发送http请求,lxml解析html,tqdm显示进度条.
主要功能 爬取某个网站的所有图片,将某个文件夹下的图片全部上传.
一天随便写了写,比较菜还请见谅.
用户类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| import sys import requests class User: def __init__(self): self.access_token = None self.__appId = input('请输入您的appid:') self.__appSecret = input('请输入您的appsecret:') self.logintime = 3 self.login()
def login(self): while self.logintime: try: res = requests.get( f"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={self.__appId}&secret={self.__appSecret}", ) if res.status_code == 200: self.access_token = res.json()['access_token'] else: print('输入错误!请尝试再次输入,还剩' + self.logintime + '次机会') except Exception as e: print('错误', res.json(), e) self.logintime = self.logintime - 1
def quit(self): print('退出') sys.exit(0)
|
这里就是注册 没什么好说的 可以增加一个错误机会.
获取图片类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| import os.path import tqdm import requests from lxml import etree import sys
class Article: def __init__(self): self.__url = None self.title = None self.__header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) ' 'Chrome/108.0.0.0 Safari/537.36 Edg/108.0.1462.54' } self.filepathList = set() self.getUpdated()
def getUpdated(self): url = 'https://www.pixivision.net/zh/c/illustration' res = requests.get(url,headers=self.__header) selector = etree.HTML(res.text) lastUpdatedNumber = selector.xpath("//li[@class='article-card-container'][1]/article/div[@class='arc__thumbnail-container']/a[1]/@href")[0] lastUpdatedNumber = lastUpdatedNumber.split('/')[-1] print('最新的图文号为',lastUpdatedNumber)
def getarticle(self): self.__url = input('输入网站链接(仅限pixvision:https://www.pixivision.net/zh/a/number):') if self.__url.isnumeric(): self.__url = 'https://www.pixivision.net/zh/a/' + self.__url try: res = requests.get(self.__url, headers=self.__header) except requests.exceptions.ProxyError as e: print('网络出现问题', e) sys.exit(-1) return except Exception as e: print('出错', e) sys.exit(-1) return selector = etree.HTML(res.text) imgLinks = selector.xpath( "////div[@class='_feature-article-body']/div[@class='article-item _feature-article-body__pixiv_illust']//div[@class='am__work__main']//img/@src") self.title = selector.xpath("//h1[@class='am__title']/text()") self.download(imgLinks)
def download(self, imgLinks): filepath = input('输入下载的目录路径(默认F:\公众号\图片):')
if not os.path.exists(filepath): print('目录输入错误') return absfilepath = filepath + f'\\{self.title}' if os.path.exists(absfilepath): print('清空文件夹中的文件') del_list = os.listdir(absfilepath) for f in del_list: file_path = os.path.join(absfilepath, f) if os.path.isfile(file_path): os.remove(file_path) else: print('生成文件夹') os.mkdir(absfilepath) self.filepathList.add(absfilepath) self.__header['Referer'] = 'https://www.pixiv.net/' pbar = tqdm.tqdm(imgLinks) total = len(imgLinks) for index, link in enumerate(pbar): filename = link.split('/')[-1] pbar.set_description("正在下载%s," % filename) pbar.set_postfix({'current': index + 1, 'total': total}) try: res = requests.get(link, headers=self.__header) with open(absfilepath + f'\\{filename}', 'wb+') as f: f.write(res.content) except Exception as e: print('需要设置代理', e)
|
这里主要利用xpath解析获取到的网页.
上传素材类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| import tqdm import requests import os
class upload: def __init__(self, ACCESS_TOKEN, FILEPATHLIST): self.url = f'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={ACCESS_TOKEN}&type' \ f'=image' self.filepath = FILEPATHLIST self.uploadPics()
def uploadPics(self):
if isinstance(self.filepath, str): self.uploadPic(self.filepath) else: for f in self.filepath: self.uploadPic(f)
def uploadPic(self, filepath): if os.path.isdir(filepath): filelist = os.listdir(filepath) total = len(filelist) pbar = tqdm.tqdm(filelist) for index, f in enumerate(pbar): file_path = os.path.join(filepath, f) if os.path.isfile(file_path): with open(file_path, 'rb') as file: files = { 'media': file } res = requests.post(self.url, files=files) pbar.set_description('正在上传' + res.json()['url']) pbar.set_postfix({'current': index + 1, 'total': total}) else: print('文件夹错误', filepath)
|
注意:requests上传FormData 需要利用files
主文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| import time from user import User from getpic import Article from uploadpic import upload
if __name__ == "__main__": uploadDownloadpic = '0' if input('直接上传图片?0表示直接上传,1表示下载\n') == '1': article = Article() while True: article.getarticle() doContinue = input('是否继续下载图片?1表示继续,0表示退出\n') if doContinue != '1': break uploadDownloadpic = input('是否上传刚才的图片?1表示是,0表示自己选择\n') u = User() if uploadDownloadpic == '1': upload(u.access_token, article.filepathList) else: filepath = input('输入需要上传的文件目录(单个):\n') upload(u.access_token, filepath)
|
总结
只是连续写了一会就累了,最近有点忙,利用这个工具上传素材到微信公众号方便水文章.最后可以利用pyinstaller打包