Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己

栏目: Go · 发布时间: 5年前

内容简介:算是第一次接触Go语言,从Runoob看了一中午的基础教程,了解了一些常用语法。最近看到掘金有一位前端大佬发布了两篇 Nodejs定时给女朋友发送暖心消息的教程,决定自己也撸一个差不多的脚本。当然这篇文章很水,只能说是学会了golang的基本使用,通过面相过程的方式做了一个简单的实现。 通过实现这个小玩意儿,算是开始入go坑了吧,请多关照。在本项目中,我使用golang来整理微信聊天记录,然后拼接成HTML,发到自己的邮箱。 这里提供两篇其他的教程,有女朋友的可以学习一下:1.

算是第一次接触 Go 语言,从Runoob看了一中午的基础教程,了解了一些常用语法。最近看到掘金有一位前端大佬发布了两篇 Nodejs定时给女朋友发送暖心消息的教程,决定自己也撸一个差不多的脚本。当然这篇文章很水,只能说是学会了golang的基本使用,通过面相过程的方式做了一个简单的实现。 通过实现这个小玩意儿,算是开始入go坑了吧,请多关照。

写在前面

在本项目中,我使用golang来整理微信聊天记录,然后拼接成HTML,发到自己的邮箱。 这里提供两篇其他的教程,有女朋友的可以学习一下:

1. 用Node+wechaty写一个爬虫脚本每天定时给女朋友发微信暖心话 2. 用Node + EJS写一个爬虫脚本每天定时女朋友发一封暖心邮件

当然,如果你没有女朋友的话,可以自己发到自己的邮箱,本篇采用这种做法。

少废话,先看东西:

Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己

技术实现

  1. Golang操作sqlite,获取聊天记录
  2. 使用 net/smtp 发送邮件
  3. 关于获取微信聊天记录内容 (目前在研究一个开源py代码,分析一下微信是如何操作 sqlite 的)

代码部分

Golang操作sqlite,获取聊天记录

微信的聊天记录是存储在sqlite中的,部分设备拿到没有经过任何加密的**.sqlite** 文件

Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己

目前在数据库中发现了这些表,还有一些以**ChatExt2_ 为前缀的表,后面与 Chat_ 前缀的表一一对应。 每一个 Chat_ 表代表与一个好友的聊天记录,目前还没有找到高效的方法确定表名与好友的关系,(Friend表居然是空的,不知道是不是我打开的方式不对,这里有待研究), 点开 Chat_**表可以看到和好友的聊天记录,当然这些数据是和手机上看到的数据是一样的,比如你在手机上左滑删除了好友,那么聊天记录在这里面也是找不到的。

这里我用了一个最笨的方法去找到了那个我需要的表,那就是一一遍历表,然后统计出表中的数据条数,最后冒泡 排序 一下,找到这个记录最多的那个表。(我很确定记录最多的那个表就是我想要的那个表)

Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己

这里可以看到 Chat_ ,**ChatExt2_ 排名最高,但是实际文本内容在 Chat_**表中。 (93020条数据,其中包括682条'对方已撤回'和'被对方拒收'这样的系统提示)

具体表结构是这样的

Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己
  • CreateTime: 发消息时间
  • Desc: 目前只看到两个值 0表示自己发的,1表示对方
  • ImgStatus: 猜测是记录视频,音频,图片和表情包的
  • MsgLocalID: 消息本地ID
  • Message: 消息主体 (基本都是文本和emoji,图片和表情以xml的形式出现,图片音视频以出现,当然里面都是id,没有实际的媒体URL)
  • MsgSvrId: 消息在服务器的ID
  • Status: 目前看到的是2表示自己发的,4表示对方发的/系统提示(已撤回,已拒收),5表示被拒收的消息(没有发过去,只存到了本地数据库)
  • TableVer: 都是1,没发现什么问题
  • Type: 1是文本,47是表情,49是分享卡片,10000是系统消息,别的就不分析了,可以通过Type和Status判断是对方发的还是系统发的

这里我主要是通过传进来两个时间去查询该时间段的消息。

// 记得import "database/sql", _ "github.com/mattn/go-sqlite3" 来操作数据库

// 聊天记录struct
type Message struct {
	create_time int64
	content 	string
	status 		int
	msg_type 	int
}

/**
 * 数据库操作
 */
func getMessages(start, end int64) []Message {
	db, err := sql.Open("sqlite3", DatabasePath)
	checkErr(err)

	sql := "SELECT `CreateTime`, `Message`, `Status`, `Type` FROM '" + DatabaseName + "' WHERE  `CreateTime` BETWEEN " + strconv.FormatInt(start,10) + " AND " + strconv.FormatInt(end,10) + " ORDER BY `CreateTime` ASC"
	rows, err := db.Query(sql)
	checkErr(err)

	data := make([]Message, 0)
	for rows.Next() {
		var message Message
		err = rows.Scan(&message.create_time, &message.content, &message.status, &message.msg_type)
		checkErr(err)

		data = append(data, message)
	}

	db.Close()
	return data
}
复制代码

时间的生成上我觉得Go有点麻烦,也可能是我姿势不对

/**
 * 时间获取封装
 */
func getTime() (int64, int64) {
	start_time := time.Now().Format(TimeFormat)
	t, _ := time.Parse(TimeFormat, start_time)
	
    start_time_unix := (BeignTime - t.Unix() + SoLikeU + 8 * 3600)	// 记得减去8个小时的时间戳
	end_time_unix := start_time_unix + (26 * 3600)					// 到第二天凌晨两点吧,因为你也会失眠睡不着
	
	return start_time_unix, end_time_unix
}
复制代码

这里是想通过获取某一天的0点时刻到第二天的2点 (也就是一天的时间+半夜睡不着的那段时间)

中间BeignTime和SoLikeU都是我自己定义的常量,后续在完整代码提供

这里使用了一个方法去获取当天的0点时刻

timeStr := time.Now().Format("2006-01-02")
fmt.Println("timeStr:", timeStr)
t, _ := time.Parse("2006-01-02", timeStr)
timeNumber := t.Unix()
fmt.Println("timeNumber:", timeNumber)
复制代码

但是这个方法会返回当天8点而不是0点,所以需要自己手动减去8个小时。

另外go的时间格式化上,并不像其他语言那样用"yyyy-mm-dd hh:mm:ss", 而是用了一个固定的时间: 2006/1/2 15:04:05 , 当初在学习时间格式转化的时候,搜了很多文章发现都是写了这么一个时间,总觉得那些博主不够专业,怎么随随便便的写个时间而不是用ymd,后来索性改成了自己的某个纪念日,结果是有问题的。

所以我觉得时间格式转换对新手很不友好,当然写过之后就记得了 (2006/1/2 15:04:05 分别是1,2,下午3点,4,5)

拼接HTML

当然这里没有什么好讲的,我采用的是最原始的HTML拼接方式,这种方式感觉在前端开发的时候经常用到。

/**
 * HTML生成
 */
func createHTML(data []Message, unix int64) string {
	html_header := "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\"content=\"width=device-width, initial-scale=1.0\"><meta http-equiv=\"X-UA-Compatible\"content=\"ie=edge\"><title>mango</title></head><style>html,body{height:100%;margin:0;padding:0}.header{width:100%;height:100px}.red-span{font-size:24px;color:rgb(221,73,73)}</style><body>"
	html_tip := "<div class=\"header\">" + 
					"<div style=\"width:100%; margin: 40px auto;font-size:20px; color:#5f5e5e;text-align:center\">" +
						"<span class=\"red-span\"> " + time.Unix(unix, 0).Format(TimeFormat) + " </span> <br>" + 
						"<span>你们一共聊了</span>" + 
						"<span class=\"red-span\">" + strconv.Itoa(len(data)) + "</span>" + 
						"<span>句</span>" + 
					"</div>" +
				"</div>"
	html_content := "<div class=\"lite-chatbox\">" 

	// 切片遍历是个坑
	for index, msg := range data {
		if index % 10 == 0 {
			html_content += "<div class=\"tips\">" + 
								"<span>" + time.Unix(msg.create_time, 0).Format("15:04:05") + "</span>" + 
							"</div>"
		}

		if msg.status == 4 {
			// 表示对方发来的消息
			html_content += "<div class=\"cleft cmsg\">" +
								"<img class=\"headIcon radius\" ondragstart=\"return false;\"  oncontextmenu=\"return false;\" src=\"" + MangoAvatar + "\" />" + 
									"<span class=\"name\">" + MangoName + "</span>"
		} else {
			// 自己发送的消息
			html_content += "<div class=\"cright cmsg\">" +
								"<img class=\"headIcon radius\" ondragstart=\"return false;\"  oncontextmenu=\"return false;\" src=\"" + XzkAvatar + "\" />" + 
									"<span class=\"name\">" + XzkName + "</span>"
		}

		html_content += "<span class=\"content\">" + msg.content + "</span>" + "</div>"
	}

	html_bottom := "<div class=\"header\">" + 
						"<div style=\"width:100%; margin: 40px auto;font-size:20px; color:#5f5e5e;text-align:center\">" +
							"<span>加油鸭</span><br/>" + 
							"<span>记得背单词,刷算法,减肥</span><br/>" + 
						"</div>" +
					"</div>" +
				"</div>" + 
				"</body></html>"
	html_css := "<style>.lite-chatbox{padding:0;width:100%;position:relative;overflow-y:auto;overflow-x:hidden;font:18px Helvetica,\"PingFang SC\",\"Microsoft YaHei\",sans-serif}.lite-chatbox .cmsg{position:relative;margin:4px 7px;min-height:50px;border:0}.lite-chatbox .cright{text-align:right;margin-left:64px}.lite-chatbox .cleft{text-align:left;margin-right:64px}.lite-chatbox img.headIcon{width:34px;height:34px;top:9px;position:absolute;border:1px solid #c5d4c4}.lite-chatbox .name{color:#8b8b8b;font-size:12px;display:block;line-height:18px}.lite-chatbox .name .htitle{display:inline-block;padding:0 3px;background-color:#ccc;color:#fff;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;margin-right:4px;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:50px}.lite-chatbox .content{word-break:break-all;word-wrap:break-word;text-align:left;position:relative;display:inline-block;font-size:15px;padding:10px 15px;line-height:20px;min-width:9px;min-height:18px}.lite-chatbox .content img{width:100%;height:auto}.lite-chatbox .content a{color:#0072C1;margin:0 5px;cursor:hand}.lite-chatbox .tips{margin:12px;text-align:center;font-size:12px}.lite-chatbox .tips span{display:inline-block;padding:4px;background-color:#ccc;color:#fff;-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.lite-chatbox img.radius{-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}.lite-chatbox .cright img.headIcon{right:0}.lite-chatbox .cleft img.headIcon{left:0}.lite-chatbox .cright .name{margin:0 48px 2px 0}.lite-chatbox .cleft .name{margin:0 0 2px 48px}.lite-chatbox .cright .content{margin:0 48px 0 0;-webkit-border-radius:20px 0 20px 20px;border-radius:20px 0 20px 20px;color:#fff;background:-webkit-linear-gradient(70deg,#3FD1E1 0%,#44D7CD 100%);background:linear-gradient(20deg,#3f8fe1cc 0%,#44d7c9 100%);-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,0.15);box-shadow:5px 5px 15px 0 rgba(102,102,102,0.15)}.lite-chatbox .cleft .content{margin:0 0 0 48px;-webkit-border-radius:0 20px 20px 20px;border-radius:0 20px 20px 20px;color:#666;border:1px solid rgba(0,0,0,0.05);background:#FFF;-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,0.1);box-shadow:5px 5px 15px 0 rgba(102,102,102,0.1)}.lite-chatbox .cright .content:after{right:-12px;top:8px}.lite-chatbox .cleft .content:after{left:-12px;top:8px}.lite-chatbox .tips .tips-primary{background-color:#3986c8}.lite-chatbox .tips .tips-success{background-color:#49b649}.lite-chatbox .tips .tips-info{background-color:#5bb6d1}.lite-chatbox .tips .tips-warning{background-color:#eea948}.lite-chatbox .tips .tips-danger{background-color:#e24d48}.lite-chatbox .name .admin{background-color:#72D6A0}.lite-chatbox .name .owner{background-color:#F2BF25}</style>"
			
	html := html_header + html_css +  html_tip + html_content + html_bottom + html_css
	
	return html
}

复制代码

这里用到了一个前端第三方框架, LiteWebChat_Frame ,可以快速搭建聊天界面。

Golang入坑笔记 – 整理了和她的9万条微信聊天记录,每天通过邮件分享给自己

在封装HTML的时候,一定要注意所有的css必须本地化,不可以采用引入的方式去加载css,但是图片是可以的。这跟邮件的某些安全策略有关吧,所以我在中间拼了一个超级长的style。

发送邮件

发送邮件用到了 "net/smtp" 包。

这里基本配置应该可以看得懂,主要是登录账号,发送邮件

最重要的是设置content_type, 只有设置为 Content-Type: text/html; charset=UTF-8 才可以发送这种html模板的邮件。

**另外有一个大坑。**不知道在什么时候开始,很多邮箱登录都需要使用授权码登录而不是密码。这个在之前某一篇 PHP 笔记中也提到过,大家可以去邮箱的设置中心查看授权码。这里我用163邮箱测试。

最后选择163而不是qq的原因是,QQ可能对资源加载做了更多的限制,我在HTML中插入的超长css代码被过滤掉了,最后显示的是一个乱版的邮件,而163没有任何问题。

// import "net/smtp"

/**
 * 发送邮件
 */
func sendMail(html string) {
	auth := smtp.PlainAuth("", "需要登录的邮箱", "授权码", "smtp.163.com")
    to := []string{"发送的邮箱"}
    nickname := "昵称"
    user := "显示的邮箱"
    subject := "邮件标题"
    content_type := "Content-Type: text/html; charset=UTF-8"
	body := html
    msg := []byte("To: " + strings.Join(to, ",") + "\r\nFrom: " + nickname +
        "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
    err := smtp.SendMail("smtp.163.com:25", auth, user, to, msg)
	checkErr(err)
	
	fmt.Println("邮件发送成功")
}
复制代码

总结

对Golang总结:

第一次写Golang,发现有些地方确实简单,例如 := 定义变量,但是和 Python 无需事先声明变量比,新手可能很容易忘记 : 而只写 = , 其次元组很方便,可以接受多个返回值,第一次接触不借助中间值对ab进行交换也是在go中学到的(a, b = b, a)

go也提供了很多好用的包,这个需要慢慢学习。

时间格式化上可能对新手有些懵逼,后续自己可以手动封装一个时间管理util。

当然语言只是工具,了解了语法之后,简单的上手还是很容易的,接触过Python,Swift后,觉得go的语法也很容易接受

对项目总结

该项目只是通过面相过程的方式去实现了一个小小的功能,没有任何的优化,所以后续我需要去深入了解GO的使用。

同时给自己埋下两个坑吧:

  1. 学会Go的高级用法
  2. 既然已经有了聊天记录资源,是否可以通过机器学习等技术训练一个对话机器人。

完整代码 (代码low,请见谅)

package main

import (
	"fmt"
	"time"
	"strings"
	"strconv"
	"net/smtp"
	"io/ioutil"
	"database/sql"
	_ "github.com/mattn/go-sqlite3"
)

// 聊天记录struct
type Message struct {
	create_time int64
	content 	string
	status 		int
	msg_type 	int
}

const (
	DatabasePath	= "/Users/xzk/Downloads/Applications/com.tencent.xin/Documents/4fa8684bdeae2190a5963a404b0cf007/DB/MM.sqlite"
	DatabaseName 	= "Chat_1a6c5c5787382c86b99ba9f72c0732dc"
	TimeFormat 		= "2006/1/2"
	BeignTime		= 1551369600	// 19.3.1 00:00:00
	SoLikeU			= 1525795200	// 2018/5/9 18:18:21
	
	MangoName		= ":sparkling_heart:对方昵称,用在HTML"
	MangoAvatar		= "对方的头像,用在HTML"
	XzkName			= "我的昵称,用在HTML"
	XzkAvatar		= "我的头像,用在HTML"

    // html输出路径,做了存储
	FilePath		= "/Users/xzk/Desktop/xzk/mango/"
	
)

func main() {

	now := time.Now().Format("2006/1/2 15:04:05")
	start_time, end_time := getTime()

	println("现在是: ", now);

	println("今天整理的是: [ ", time.Unix(start_time, 0).Format("2006/1/2 15:04:05"), " - " , time.Unix(end_time, 0).Format("2006/1/2 15:04:05"), " ] 的故事")

	data := getMessages(start_time, end_time)
	// for _, msg:= range data {
	// 	fmt.Println(msg)
	// }

	html := createHTML(data, start_time)
	saveAndSend(html, start_time)

	fmt.Println("Bye~")
}

/**
 * 时间获取封装
 */
func getTime() (int64, int64) {
	start_time := time.Now().Format(TimeFormat)
	t, _ := time.Parse(TimeFormat, start_time)
	
    start_time_unix := (BeignTime - t.Unix() + SoLikeU + 8 * 3600)	// 记得减去8个小时的时间戳
	end_time_unix := start_time_unix + (26 * 3600)					// 到第二天凌晨两点吧,因为你也会失眠睡不着
	
	return start_time_unix, end_time_unix
}

/**
 * 数据库操作
 */
func getMessages(start, end int64) []Message {
	db, err := sql.Open("sqlite3", DatabasePath)
	checkErr(err)

	sql := "SELECT `CreateTime`, `Message`, `Status`, `Type` FROM '" + DatabaseName + "' WHERE  `CreateTime` BETWEEN " + strconv.FormatInt(start,10) + " AND " + strconv.FormatInt(end,10) + " ORDER BY `CreateTime` ASC"
	rows, err := db.Query(sql)
	checkErr(err)

	data := make([]Message, 0)
	for rows.Next() {
		var message Message
		err = rows.Scan(&message.create_time, &message.content, &message.status, &message.msg_type)
		checkErr(err)

		data = append(data, message)
	}

	db.Close()
	return data
}

/**
 * HTML生成
 */
func createHTML(data []Message, unix int64) string {
	html_header := "<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta name=\"viewport\"content=\"width=device-width, initial-scale=1.0\"><meta http-equiv=\"X-UA-Compatible\"content=\"ie=edge\"><title>mango</title></head><style>html,body{height:100%;margin:0;padding:0}.header{width:100%;height:100px}.red-span{font-size:24px;color:rgb(221,73,73)}</style><body>"
	html_tip := "<div class=\"header\">" + 
					"<div style=\"width:100%; margin: 40px auto;font-size:20px; color:#5f5e5e;text-align:center\">" +
						"<span class=\"red-span\"> " + time.Unix(unix, 0).Format(TimeFormat) + " </span> <br>" + 
						"<span>你们一共聊了</span>" + 
						"<span class=\"red-span\">" + strconv.Itoa(len(data)) + "</span>" + 
						"<span>句</span>" + 
					"</div>" +
				"</div>"
	html_content := "<div class=\"lite-chatbox\">" 

	for index, msg := range data {
		if index % 10 == 0 {
			html_content += "<div class=\"tips\">" + 
								"<span>" + time.Unix(msg.create_time, 0).Format("15:04:05") + "</span>" + 
							"</div>"
		}

		if msg.status == 4 {
			// 表示对方发来的消息
			html_content += "<div class=\"cleft cmsg\">" +
								"<img class=\"headIcon radius\" ondragstart=\"return false;\"  oncontextmenu=\"return false;\" src=\"" + MangoAvatar + "\" />" + 
									"<span class=\"name\">" + MangoName + "</span>"
		} else {
			// 自己发送的消息
			html_content += "<div class=\"cright cmsg\">" +
								"<img class=\"headIcon radius\" ondragstart=\"return false;\"  oncontextmenu=\"return false;\" src=\"" + XzkAvatar + "\" />" + 
									"<span class=\"name\">" + XzkName + "</span>"
		}

		html_content += "<span class=\"content\">" + msg.content + "</span>" + "</div>"
	}

	html_bottom := "<div class=\"header\">" + 
						"<div style=\"width:100%; margin: 40px auto;font-size:20px; color:#5f5e5e;text-align:center\">" +
							"<span>加油鸭</span><br/>" + 
							"<span>记得背单词,刷算法,减肥</span><br/>" + 
						"</div>" +
					"</div>" +
				"</div>" + 
				"</body></html>"
	html_css := "<style>.lite-chatbox{padding:0;width:100%;position:relative;overflow-y:auto;overflow-x:hidden;font:18px Helvetica,\"PingFang SC\",\"Microsoft YaHei\",sans-serif}.lite-chatbox .cmsg{position:relative;margin:4px 7px;min-height:50px;border:0}.lite-chatbox .cright{text-align:right;margin-left:64px}.lite-chatbox .cleft{text-align:left;margin-right:64px}.lite-chatbox img.headIcon{width:34px;height:34px;top:9px;position:absolute;border:1px solid #c5d4c4}.lite-chatbox .name{color:#8b8b8b;font-size:12px;display:block;line-height:18px}.lite-chatbox .name .htitle{display:inline-block;padding:0 3px;background-color:#ccc;color:#fff;-moz-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;margin-right:4px;font-size:11px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;max-width:50px}.lite-chatbox .content{word-break:break-all;word-wrap:break-word;text-align:left;position:relative;display:inline-block;font-size:15px;padding:10px 15px;line-height:20px;min-width:9px;min-height:18px}.lite-chatbox .content img{width:100%;height:auto}.lite-chatbox .content a{color:#0072C1;margin:0 5px;cursor:hand}.lite-chatbox .tips{margin:12px;text-align:center;font-size:12px}.lite-chatbox .tips span{display:inline-block;padding:4px;background-color:#ccc;color:#fff;-moz-border-radius:6px;-webkit-border-radius:6px;border-radius:6px}.lite-chatbox img.radius{-moz-border-radius:100%;-webkit-border-radius:100%;border-radius:100%}.lite-chatbox .cright img.headIcon{right:0}.lite-chatbox .cleft img.headIcon{left:0}.lite-chatbox .cright .name{margin:0 48px 2px 0}.lite-chatbox .cleft .name{margin:0 0 2px 48px}.lite-chatbox .cright .content{margin:0 48px 0 0;-webkit-border-radius:20px 0 20px 20px;border-radius:20px 0 20px 20px;color:#fff;background:-webkit-linear-gradient(70deg,#3FD1E1 0%,#44D7CD 100%);background:linear-gradient(20deg,#3f8fe1cc 0%,#44d7c9 100%);-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,0.15);box-shadow:5px 5px 15px 0 rgba(102,102,102,0.15)}.lite-chatbox .cleft .content{margin:0 0 0 48px;-webkit-border-radius:0 20px 20px 20px;border-radius:0 20px 20px 20px;color:#666;border:1px solid rgba(0,0,0,0.05);background:#FFF;-webkit-box-shadow:5px 5px 15px 0 rgba(102,102,102,0.1);box-shadow:5px 5px 15px 0 rgba(102,102,102,0.1)}.lite-chatbox .cright .content:after{right:-12px;top:8px}.lite-chatbox .cleft .content:after{left:-12px;top:8px}.lite-chatbox .tips .tips-primary{background-color:#3986c8}.lite-chatbox .tips .tips-success{background-color:#49b649}.lite-chatbox .tips .tips-info{background-color:#5bb6d1}.lite-chatbox .tips .tips-warning{background-color:#eea948}.lite-chatbox .tips .tips-danger{background-color:#e24d48}.lite-chatbox .name .admin{background-color:#72D6A0}.lite-chatbox .name .owner{background-color:#F2BF25}</style>"
			
	html := html_header + html_css +  html_tip + html_content + html_bottom + html_css
	
	return html
}

/**
 * 存储生成的网站
 */
func saveAndSend(html string, unix int64) {
	file_path := FilePath + time.Unix(unix, 0).Format("2006-01-02") + ".html"
	println(file_path)
	_, err := ioutil.ReadFile(file_path)
    if err != nil {
		// 文件不存在, 写入文件存档
		bytes := []byte(html)
		err := ioutil.WriteFile(file_path, bytes, 0644)
		checkErr(err)

		fmt.Println("文件已经保存,开始发送邮件")

		// 发送邮件
		sendMail(html)
    } else {
		// 文件已经存在,可能已经发送过email
		fmt.Println(file_path + " 文件已经存在,可能已发送过邮件")
	}
}

/**
 * 发送邮件
 */
func sendMail(html string) {
	auth := smtp.PlainAuth("", "xxx@163.com", "xxx", "smtp.163.com")
    to := []string{"xxx@163.com"}
    nickname := ""
    user := "xxx@163.com"
    subject := "xxxx"
    content_type := "Content-Type: text/html; charset=UTF-8"
	body := html
    msg := []byte("To: " + strings.Join(to, ",") + "\r\nFrom: " + nickname +
        "<" + user + ">\r\nSubject: " + subject + "\r\n" + content_type + "\r\n\r\n" + body)
    err := smtp.SendMail("smtp.163.com:25", auth, user, to, msg)
	checkErr(err)
	
	fmt.Println("邮件发送成功")
}

/**
 * 错误检测
 */
func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}
复制代码

写在尾部: 我想学习如何通过这些聊天记录来训练一个聊天机器人,但是作为开发狗对机器学习或者其他技术并不了解,希望懂的big brother给指条明路。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

长尾理论

长尾理论

[美] 克里斯·安德森 / 乔江涛 / 中信出版社 / 2006-12 / 35.00元

书中阐述,商业和文化的未来不在于传统需求曲线上那个代表“畅销商品”(hits)的头部; 而是那条代表“冷门商品”(misses)经常为人遗忘的长尾。 举例来说, 一家大型书店通常可摆放10万本书,但亚马逊网络书店的图书销售额中,有四分之一来自排名10万以后的书籍。这些“冷门”书籍的销售比例正以高速成长,预估未来可占整体书市的一半。 这意味着消费者在面对无限的选择时,真正想要的东西、和想要取得......一起来看看 《长尾理论》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具