前言
python忠实用户,尝试自动化写文章到订阅号,找了半天发现一篇写的还不错的,可惜参考的网站已经没有了,找了一篇类似的网页复现了一下功能。为后期自己自动化的程序做准备,顺便分享给大家;
一、需求与难点
- 1.从指定页面爬取数据
- 2.只爬取我们需要的内容(什么广告啊,导航那种是不要的)
- 3.然后把正文上传到微信公众号的草稿箱
- 4.微信的草稿箱接口只能放上传到微信里面的图片,所以我们要做一步额外的操作就是先把网页里面的图片提取出来上传到微信公众号里面,然后把正文里面的图片链接替换成微信公众号里面的 图片
二、使用到的工具和接口
python 这边主要使用:requests,BeautifulSoup,json ,
- 上传封面图片到微信公众号 新增永久图文素材 | 微信开放文档 (qq.com)
- 上传正文图片到微信公众号
- http请求方式:
-
POST,https协议 https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN 调用示例(使用curl命令,用FORM表单方式上传一个图片): curl -F media=@test.jpg "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=ACCESS_TOKEN"
- 上传正文到公众号草稿箱 接口请求说明 | 微信开放文档 (qq.com)
三、实现步骤
1.分析网页
网页地址: 绘本分享:Down by the Station
我们可以看出这个网页有自己的导航还有右边的推荐栏还有底部的导航,如果我们直接吧整个网页都扣下来上传到的微信公众号那无疑会给我们后期处理带来很多的工作,所以我们只需要正文也就是html里面的<article></article>里面的内容
分析网页我们可以得到我们要的title就在class = 'entry-title'的a标签里面,而且我们还可以拿到文章的摘要在section的里面,所以我们首先抓取这个页面然后拿到title和摘要, 之类要去掉html的格式,只保留文本内容;
baseUrl = 'https://www.meipian.cn/2nwoqrio'
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36 Edg/96.0.1054.57'
}
res = requests.get(baseUrl, verify=False, headers=headers)
root_soup = BeautifulSoup(res.content, 'html.parser')
title = root_soup.select('title')[0].text
summary = root_soup.select('section')[0].text.replace('<div>','').replace('<br>','').replace('</div>','')
print(title)
print(summary)
2. 调用接口
我们先来看上传草稿API接口【来自微信,如果又变化请自行检查微信平台接口即可,目前测试仍旧可用】
http 请求方式:POST(请使用https协议)https://api.weixin.qq.com/cgi-bin/draft/add?access_token=ACCESS_TOKEN
调用示例
{
"articles": [
{
"title":TITLE,
"author":作者(会展示在发布后的文章里),
"content":CONTENT(这里需要时html的格式),
"content_source_url":CONTENT_SOURCE_URL,
"thumb_media_id":THUMB_MEDIA_ID这里需要先把封面上传到微信(),
"show_cover_pic":1,
"need_open_comment":0,
"only_fans_can_comment":0
}
//若新增的是多图文素材,则此处应还有几段articles结构
]
}
请求参数说明
参数 是否必须 说明
【下面就是如何从网页中获得上述调用接口需要的内容了,主要就是封面图片,内容,自己内容里面的额图片如何上传到微信】
2.1 上传封面
接下来要准备搞定封面,在使用公众号接口之前我们要先获取一个token,来使我们有权限访问公众号的API接口,获取token的代码:
## 此函数用于获取access_token,不知道有啥作用,参考微信公众号开发文档:https://developers.weixin.qq.com/doc/offiaccount/Basic_Information/Get_access_token.html
# // 获取token
def get_wxCode_token():
try:
appid = ""
secret = ""
textmod = {"grant_type": "client_credential",
"appid": appid,
"secret": secret
}
textmod = parse.urlencode(textmod)
header_dict = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36'}
url = 'https://api.weixin.qq.com/cgi-bin/token'
req = request.Request(url='%s%s%s' % (url, '?', textmod), headers=header_dict)
res = request.urlopen(req)
res = res.read().decode(encoding='utf-8')
res = json.loads(res)
access_token = res["access_token"]
print('access_token:',(access_token,time.time()))
return (access_token,time.time())
except Exception as e:
print(res)
print(e)
return False
通过分析正文我们知道这个文章有很多图片,那我们就把第一个图片单做封面,先定义一个上传封面的方法:
def updFm(path, file_name):
base_folder = './'
file_path = '{}{}.jpg'.format(base_folder, file_name)
res = requests.get(path, verify=False)
with open(file_path, 'wb') as f:
f.write(res.content)
url = 'https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={}&type={}'.format(access_token, 'image')
request_file = {
'media': ('{}.jpg'.format(file_name), open(file_path, 'rb'), 'image/jpeg')}
vx_res = requests.post(url=url, files=request_file)
obj = json.loads(vx_res.content)
print(obj)
return obj['media_id']
分析发现在原网页是通过代码动态生成的网页内容,代码使用的是json的格式,可以通过下面的方式获取到封面id:
content_soup = re.search('({.+})', root_soup.select('script')[0].text).group(0)
content_soup_dict = eval(content_soup.replace('false', '').replace('null', '""').replace('<div>', '').replace('<br>', '').replace(
'</div>', '').replace('<br />', '').replace(':,', ':"",').replace(':}', ':""}'))
text_imgs = content_soup_dict['content']
fmID = content_soup_dict['article']['cover_img_url']
2.2 上传内容中的图片
接下来我们在定义一个上传正文其他图片的方法,因为其他图片需要返回的url不是media_id,所以调的另外一个接口
def updImg(url):
base_folder = './temp'
res = requests.get(url, verify=False)
file_name = '{}.jpg'.format(random.randint(10000, 99999))
with open(base_folder + file_name, 'wb') as f:
f.write(res.content)
vx_img_url = 'https://api.weixin.qq.com/cgi-bin/media/uploadimg'
request_file = {
'media': (file_name, open(base_folder + file_name, 'rb'), 'image/jpeg')}
data = {
'access_token': access_token
}
vx_res = requests.post(url=vx_img_url, files=request_file, data=data)
obj = json.loads(vx_res.content)
print(obj)
return obj['url']
然后把正文里面的图片全部上传到微信公众号号的素材库并替换到正文里面的图片地址
content_text_full=''
for img_content in text_imgs:
current_text = img_content['text']
current_url = img_content['img_url']
content_text_full+=current_text +'<br/>'
if len(current_url) >=10:
upd_url = updImg(current_url)
content_text_full+=f'<img src={upd_url } /><br/>'
print('current_text',current_text)
print('current_url', current_url)
最后我们就可以开始准备上传文章到草稿箱,还是先定义方法,因为草稿接口的标题和摘要有长度限制所以这个方法开始做了一个限制如果长度超过了就截取字符串
def updCG(title, summary, content, fmId):
if len(title) > 64:
title = title[:63]
if len(summary) > 120:
summary = summary[:119]
url = 'https://api.weixin.qq.com/cgi-bin/draft/add?access_token=' + access_token
data = {
"articles": [
{
"title": title,
"author": '作者',
"digest": summary,
"content": content,
"show_cover_pic": 1,
"need_open_comment": 0,
"only_fans_can_comment": 0,
"thumb_media_id": fmId
}
]
}
vx_res = requests.post(url=url, data=json.dumps(
data, ensure_ascii=False).encode("utf-8"))
obj = json.loads(vx_res.content)
print(obj)
return obj['media_id']
然后再总方法里面调用我们的上传草稿的方法
updCG(title, summary, content_text_full, fmId)
查看结果,可以看到文章已经自动提交到草稿箱,接下里我们就可以进去进行二次创作进行发表了
最终效果:
总结
本方法核心参考了前人的实现方式,但是已经不能使用了,所以尝试复现并且补全了各种功能,让各位可以看到就能复现,如果合作请私聊~