基于Golang的chromedp库实现获取Hostloc的每日热帖

295次阅读
没有评论

共计 2798 个字符,预计需要花费 7 分钟才能阅读完成。

背景

关于获取 Hostloc 的每日热帖推送的话题,本站已经写了两篇博客阐述了,分别是 你想收到 hostloc 每日热帖的邮件么?以及 如何越过 Hostloc 的防 CC 攻击机制获取其每日热帖,虽然这两个都是 Python 脚本,但是前者仅仅是一个简单的 Python 脚本,无法应对后来新增的防 CC 机制,而后者中的脚本很好的解决了这个问题,但是本篇博客用一种全新的思路来解决这个问题,具体就是用了一个把 chrome 的 cdp 协议封装成 golang 对象的库 chromedp 来调用无头的 chrome 浏览器来访问 loc 站点。

依赖

下面的脚本依赖了以下第三方 github 库,编译前自己安装一下。

"github.com/anaskhan96/soup"
"github.com/chromedp/chromedp"
"github.com/emersion/go-sasl"
"github.com/emersion/go-smtp"

代码

package main

import (
	"context"
	"encoding/base64"
	"fmt"
	"os"
	"runtime/debug"
	"strconv"
	"strings"
	"time"

	"github.com/anaskhan96/soup"
	"github.com/chromedp/chromedp"
	"github.com/emersion/go-sasl"
	"github.com/emersion/go-smtp"
)

func mailSend(mailBodyText string) {currentDate := time.Now().Format("2006-01-02")
	subject := fmt.Sprintf("%s Hostloc 今日热帖", currentDate)
	subjectBase := base64.StdEncoding.EncodeToString([]byte(subject))
	from := ""to :=""
	password := ""smtpServer :="smtp.qq.com:587"auth := sasl.NewPlainClient("", from, password)
	msg := strings.NewReader(
		"From:" + from + "\r\n" +
			"To:" + to + "\r\n" +
			"Subject: =?UTF-8?B?" + subjectBase + "?=\r\n" +
			"Content-Type: text/html; charset=UTF-8" +
			"\r\n\r\n" +
			mailBodyText + "\r\n")
	if err := smtp.SendMail(smtpServer, auth, from, []string{to}, msg); err != nil {fmt.Println(err.Error() + string(debug.Stack()))
		os.Exit(1)
	} else {fmt.Println("成功发送了一封邮件!")
	}
}

func getMailBody() string {
	urlPrefix := "https://www.hostloc.com/"
	fullUrl := urlPrefix + "forum.php?mod=forumdisplay&fid=45&filter=hot"
	// 参数设置
	options := []chromedp.ExecAllocatorOption{chromedp.Flag("headless", true),
		chromedp.Flag("disable-gpu", true),
		chromedp.UserAgent(`Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36`),
	}
	options = append(chromedp.DefaultExecAllocatorOptions[:], options...)
	allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), options...)
	defer cancel()

	// 创建 chrome 示例
	ctx, cancel := chromedp.NewContext(allocCtx)
	defer cancel()
	ctx, cancel = context.WithTimeout(ctx, 15*time.Second)
	defer cancel()

	var hotListHtml string
	if err := chromedp.Run(ctx,
		chromedp.Tasks{
			// 打开导航
			chromedp.Navigate(fullUrl),
			// 等待元素加载完成
			chromedp.WaitVisible("body", chromedp.ByQuery),
			chromedp.OuterHTML("#threadlist", &hotListHtml, chromedp.ByID),
		}); err != nil {fmt.Println(err.Error() + string(debug.Stack()))
		os.Exit(1)
	}
	doc := soup.HTMLParse(hotListHtml)
	itemList := doc.Find("div", "class", "bm_c").FindAll("tr")[2:]
	var mailBodyList []string
	for _, item := range itemList {replyNumStr := item.Find("td", "class", "num").FindStrict("a", "class", "xi2").Text()
		titleAndHref := item.Find("th", "class", "new").FindStrict("a", "class", "s xst")
		title := titleAndHref.Text()
		link := titleAndHref.Attrs()["href"]
		replyNumInt, err := strconv.Atoi(replyNumStr)
		if err != nil {fmt.Println(err.Error() + string(debug.Stack()))
			os.Exit(1)
		}
		if replyNumInt >= 35 {mailBodyList = append(mailBodyList, title+"<br/>"+urlPrefix+link)
		}
	}
	mailBodyText := strings.Join(mailBodyList[:], "</br>")
	return mailBodyText

}

func main() {mailSend(getMailBody())
}

 

正文完
 
sharp097
版权声明:本站原创文章,由 sharp097 2022-06-30发表,共计2798字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)