前情提要
以前接了圖靈機器人的api做過一個微信小機器人,但是這個機器人只會尬聊也就算了,竟然連鬥圖都不能!!!雖說圖靈機器人官網上有這個api,可是由於我是用python手動接入而不是直接授權,發送表情包給他依然會回復尬聊。我深信沒有鬥圖的機器人是沒有靈魂的,於是想動手自己寫一個。
參考:用python爬取鬥圖網
列印從用戶哪裡獲得的消息,會發現,接收表情包返回的是一行文本信息:【收到不支持的消息類型,暫無法顯示】
於是我們稍微改一改之前的代碼,對這行文本進行判斷,只要接收到這行消息,參考爬取代碼從鬥圖網隨機爬取一個表情包下載下來,再傳入臨時素材庫,獲取mediaid,再生成圖片消息發送給用戶就可以了。
效果:因為又要下載又要上傳顯得稍微有點卡頓,但是還可以。
[外鏈圖片轉存失敗(img-LcIYYqi5-1567160626891)(https://sika0819.top//images/pasted-48.png)]
核心代碼:
handler.py
import hashlibimport replyimport receiveimport webimport robotimport getemoticonfrom basic import Basicfrom media import Mediaimport jsonclass Handle(object): def GET(self): try: data = web.input() if len(data) == 0: return "hello, this is handle view" signature = data.signature timestamp = data.timestamp nonce = data.nonce echostr = data.echostr token = "yourtoken" list = [token, timestamp, nonce] list.sort() sha1 = hashlib.sha1() map(sha1.update, list) hashcode = sha1.hexdigest() if hashcode == signature: return echostr else: return "" except Exception: return Exception.message def POST(self): try: webData = web.data() recMsg=receive.parse_xml(webData) if isinstance(recMsg, receive.Msg): toUser = recMsg.FromUserName fromUser = recMsg.ToUserName if recMsg.MsgType=='text': content = recMsg.Content print(content); if content=="【收到不支持的消息類型,暫無法顯示】": path=getemoticon.getRandomEmoticon() print(path) myMedia = Media() accessToken = Basic().get_access_token() mediaType = "image" callbackjson = myMedia.upload(accessToken, path, mediaType) callback = json.loads(callbackjson) mediaId=callback[u'media_id'] createTime=callback[u'created_at'] replyMsg = reply.ImageMsg(toUser, fromUser,createTime,mediaType,mediaId) return replyMsg.send() else: rpyMsg= robot.get_response(content,fromUser) replyMsg=reply.TextMsg(toUser, fromUser,rpyMsg) return replyMsg.send() if recMsg.MsgType == 'image': mediaId = recMsg.MediaId replyMsg = reply.ImageMsg(toUser, fromUser, mediaId) return replyMsg.send() else: print("none handler yet") return "success" except Exception as Argument: print Exception.message return "fail"
media.py
from basic import Basicimport urllib2import poster.encodefrom poster.streaminghttp import register_openersclass Media(object): def __init__(self): register_openers() def upload(self, accessToken, filePath, mediaType): openFile = open(filePath, "rb") param = {'media': openFile} postData, postHeaders = poster.encode.multipart_encode(param) postUrl = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=%s&type=%s" % (accessToken, mediaType) request = urllib2.Request(postUrl, postData, postHeaders) urlResp = urllib2.urlopen(request) return urlResp.read()
reply.py
import timeclass Msg(object): def __init__(self): pass def send(self): return "success"class TextMsg(Msg): def __init__(self, toUserName, fromUserName, content): self.__dict = dict() self.__dict['ToUserName'] = toUserName self.__dict['FromUserName'] = fromUserName self.__dict['CreateTime'] = int(time.time()) self.__dict['Content'] = content def send(self): XmlForm = """ <xml> <ToUserName><![CDATA[{ToUserName}]]></ToUserName> <FromUserName><![CDATA[{FromUserName}]]></FromUserName> <CreateTime>{CreateTime}</CreateTime> <MsgType><![CDATA[text]]></MsgType> <Content><![CDATA[{Content}]]></Content> </xml> """ return XmlForm.format(**self.__dict)class ImageMsg(Msg): def __init__(self, toUserName, fromUserName, mediaId): self.__dict = dict() self.__dict['ToUserName'] = toUserName self.__dict['FromUserName'] = fromUserName self.__dict['CreateTime'] = int(time.time()) self.__dict['MediaId'] = mediaId def __init__(self, toUserName, fromUserName,createTime,msgType, mediaId): self.__dict = dict() self.__dict['ToUserName'] = toUserName self.__dict['FromUserName'] = fromUserName self.__dict['CreateTime'] = createTime self.__dict['MsgType'] = msgType self.__dict['MediaId'] = mediaId def send(self): XmlForm = """ <xml> <ToUserName><![CDATA[{ToUserName}]]></ToUserName> <FromUserName><![CDATA[{FromUserName}]]></FromUserName> <CreateTime>{CreateTime}</CreateTime> <MsgType><![CDATA[image]]></MsgType> <Image> <MediaId><![CDATA[{MediaId}]]></MediaId> </Image> </xml> """ return XmlForm.format(**self.__dict)
隨機爬取表情包
getemoticon.py
import randomimport requestsimport refrom bs4 import BeautifulSoupimport bs4import osmy_headers = [ "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.153 Safari/537.36", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:30.0) Gecko/20100101 Firefox/30.0", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; Win64; x64; Trident/6.0)",] kv = {"User-Agent": "Mozilla/5.0"} def getHTMLText(url, headers): try: random_header = random.choice(headers) r = requests.get(url, headers={"User-Agent": random_header}, timeout = 30) r.raise_for_status() r.encoding = r.apparent_encoding return r.text except: print("爬取失敗") def getImgList(Ilist, html): soup = BeautifulSoup(html, "html.parser") pattern_img = re.compile(r'data-original="(.+?)"') pattern_title = re.compile(r'alt="(.+?)"') imgList = re.findall(pattern_img, html) titleList = re.findall(pattern_title, html) for i in range(len(imgList)): titleList[i] = titleList[i].encode('utf-8') Ilist.append([imgList[i], titleList[i]]) return Ilist def mkdir(): if not os.path.exists('img'): os.mkdir('img')def saveImg(Ilistcontent): mkdir() img_content = requests.get(Ilistcontent[0]).content img_path="" if (Ilistcontent[0][-4:] == '.jpg'): img_path='img/%s.jpg' % (Ilistcontent[1].decode('utf-8')) elif (Ilistcontent[0][-4:] == '.gif'): img_path='img/%s.gif' % (Ilistcontent[1].decode('utf-8')) if os.path.exists(img_path): return img_path with open(img_path, 'wb') as f: f.write(img_content) f.close() return img_pathdef download(page): Ilist = [] url = "https://www.doutula.com/photo/list/?page=%d" %page html = getHTMLText(url, my_headers) Ilist = getImgList(Ilist, html) return Ilistdef getRandomEmoticon(): print("下載圖片") page= 1; print("第%d頁"%page) Ilist= download(page); i=random.randint(0,len(Ilist)-1) print("第%d張圖"%i) path=saveImg(Ilist[i]) return path
這裡我因為怕速度太慢只爬取了第一頁,然後從第一頁隨機下載一個圖片下來。邏輯應該還可以在優化,從本地直接上傳表情包會更快。最好的方式應該是定期下載表情包,把表情存成永久素材,每次直接調用。但由於我是個懶癌晚期,完全不想進行後臺管理,於是做成了隨用隨下載。