诺禾、abp vNext 和 .NET Core 开发博客项目

假如没有装置能够先装置一下,在.BackgroundJobs层装置PuppeteerSharp:Install-Package PuppeteerSharp

在Jobs文件夹下新建一个PuppeteerTestJob.cs,继承IBackgroundJob,同样是在ExecuteAsync()办法中执行操作。


//PuppeteerTestJob.cs
using System;
using System.Threading.Tasks;
namespace Meowv.Blog.BackgroundJobs.Jobs.PuppeteerTest
{
public class PuppeteerTestJob : IBackgroundJob
{
public async Task ExecuteAsync()
{
throw new NotImplementedException();
}
}
}
运用 await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision); 第一次检测到没有阅读器文件会默许帮我们下载 chromium 阅读器。

DownloadAsync(…)能够指定 Chromium 版本,BrowserFetcher.DefaultRevision 下载当前默许最稳定的版本。

然后配置阅读器启动的方式。


using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new string[] { “–no-sandbox” }
});
感兴味的能够本人看看LaunchOptions有哪些参数,我这里指定了Headless = true 以无头形式运转阅读器,然后加了一个启动参数 “–no-sandbox”。针对Linux环境下,假如是运转在 root 权限下,在启动 Puppeteer 时要添加 “–no-sandbox” 参数,否则 Chromium 会启动失败。

我们翻开一个异步加载的网页,然后获取到页面加载完后的HTML,以我个人博客中的某个单页为例:https://meowv.com/wallpaper 。


//PuppeteerTestJob.cs
using PuppeteerSharp;
using System.Threading.Tasks;
namespace Meowv.Blog.BackgroundJobs.Jobs.PuppeteerTest
{
public class PuppeteerTestJob : IBackgroundJob
{
public async Task ExecuteAsync()
{
await new BrowserFetcher().DownloadAsync(BrowserFetcher.DefaultRevision);
using var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new string[] { “–no-sandbox” }
});
using var page = await browser.NewPageAsync();
await page.SetViewportAsync(new ViewPortOptions
{
Width = 1920,
Height = 1080
});
var url = “https://meowv.com/wallpaper”;
await page.GoToAsync(url, WaitUntilNavigation.Networkidle0);
var content = await page.GetContentAsync();
}
}
}
page.SetViewportAsync()设置网页预览大小,page.GoToAsync()语法翻开网页,WaitUntilNavigation.Networkidle0等候网页加载终了,运用page.GetContentAsync()获取到HTML。

新建扩展办法,调用这个PuppeteerTestJob的ExecuteAsync()办法,调试看看效果。

1

HTML曾经出来了,此时该干嘛就干嘛就能够了。

第一次运转可能会很慢,由于假如你本地不存在 Chromium 是会去帮我们下载的,由于网络缘由可能会下载的很慢,所以引荐大家手动下载。

能够运用淘宝的源:https://npm.taobao.org/mirrors/chromium-browser-snapshots/ 。

要留意的是,下载完成后的解压的途径不能出错,默许下载地址是在启动目录下面。

Windows:…local-chromium\Win64-706915\chrome-win 、 Linux:…/.local-chromium/Linux-706915/chrome-linux

接下来试试生成PDF和保管图片功用,运用方式也很简单。


await page.PdfAsync(“meowv.pdf”,new PdfOptions { });
await page.ScreenshotAsync(“meowv.png”, new ScreenshotOptions
{
FullPage = true,
Type = ScreenshotType.Png
});
这里只做简单的展现,page.PdfAsync()直接生成PDF文件,同时还有很多办法能够本人调用page.试试,PdfOptions选项中能够设置各种参数。

page.ScreenshotAsync()保管图片,ScreenshotOptions中FullPage能够设置保管图片为全屏形式,图片格式为Png类型。

2

能够看到项目根目录曾经生成了图片和PDF,觉得去试试吧。

接下里来完成发送邮件的功用。

我这里发邮件的账号是用的腾讯企业邮箱,也能够用普通邮箱开通SMTP效劳即可。

在appsettings.json配置收发邮件的账号等信息。


//appsettings.json
“Email”: {
“Host”: “smtp.exmail.qq.com”,
“Port”: 465,
“UseSsl”: true,
“From”: {
“Username”: “[email protected]”,
“Password”: “[Password]”,
“Name”: “MEOWV.COM”,
“Address”: “[email protected]
},
“To”: [
{
“Name”: “test1”,
“Address”: “[email protected]
},
{
“Name”: “test2”,
“Address”: “[email protected]
}
]
}
然后再AppSettings中读取配置的项。


//AppSettings.cs
public static class Email
{
///

/// Host
/// 
public static string Host => _config["Email:Host"];
/// 

/// Port
/// 
public static int Port => Convert.ToInt32(_config["Email:Port"]);
/// 

/// UseSsl
/// 
public static bool UseSsl => Convert.ToBoolean(_config["Email:UseSsl"]);
/// 

/// From
/// 
public static class From
{
    /// 

    /// Username
    /// 
    public static string Username => _config["Email:From:Username"];
    /// 

    /// Password
    /// 
    public static string Password => _config["Email:From:Password"];
    /// 

    /// Name
    /// 
    public static string Name => _config["Email:From:Name"];
    /// 

    /// Address
    /// 
    public static string Address => _config["Email:From:Address"];
}
/// 

/// To
/// 
public static IDictionary To
{
    get
    {
        var dic = new Dictionary();
        var emails = _config.GetSection("Email:To");
        foreach (IConfigurationSection section in emails.GetChildren())
        {
            var name = section["Name"];
            var address = section["Address"];
            dic.Add(name, address);
        }
        return dic;
    }
}

}
分别引见下每项的含义:

Host:发送邮件效劳器地址。
Port:效劳器地址端口号。
UseSsl:能否运用SSL方式。
From:发件人的账号密码,称号及邮箱地址,普通邮箱地址和账号是相同的。
To:收件人邮箱列表,也包含称号和邮箱地址。
收件人邮箱列表我将其读取为IDictionary了,key是称号,value是邮箱地址。

接着在.ToolKits层添加一个EmailHelper.cs,收发邮件我选择了MailKit和MailKit两个库,没有装置的先装置一下,Install-Package MailKit、Install-Package MimeKit。

直接新建一个发送邮件的办法SendAsync(),依照请求将根本的配置信息填进去,然后直接调用即可。


//EmailHelper.cs
using MailKit.Net.Smtp;
using Meowv.Blog.Domain.Configurations;
using MimeKit;
using System.Linq;
using System.Threading.Tasks;
namespace Meowv.Blog.ToolKits.Helper
{
public static class EmailHelper
{
///

    /// 发送Email
    /// 
    /// 
    /// 
    public static async Task SendAsync(MimeMessage message)
    {
        if (!message.From.Any())
        {
            message.From.Add(new MailboxAddress(AppSettings.Email.From.Name, AppSettings.Email.From.Address));
        }
        if (!message.To.Any())
        {
            var address = AppSettings.Email.To.Select(x => new MailboxAddress(x.Key, x.Value));
            message.To.AddRange(address);
        }
        using var client = new SmtpClient
        {
            ServerCertificateValidationCallback = (s, c, h, e) => true
        };
        client.AuthenticationMechanisms.Remove("XOAUTH2");
        await client.ConnectAsync(AppSettings.Email.Host, AppSettings.Email.Port, AppSettings.Email.UseSsl);
        await client.AuthenticateAsync(AppSettings.Email.From.Username, AppSettings.Email.From.Password);
        await client.SendAsync(message);
        await client.DisconnectAsync(true);
    }
}

}
SendAsync(…)接纳一个参数MimeMessage对象,这样就完成了一个通用的发邮件办法,接着我们去需求发邮件的中央结构MimeMessage,调用SendAsync()。


//WallpaperJob.cs

// 发送Email
var message = new MimeMessage
{
Subject = “【定时任务】壁纸数据抓取任务推送”,
Body = new BodyBuilder
{
HtmlBody = $“本次抓取到{wallpapers.Count()}条数据,时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}”
}.ToMessageBody()
};
await EmailHelper.SendAsync(message);


//HotNewsJob.cs

// 发送Email
var message = new MimeMessage
{
Subject = “【定时任务】每日热点数据抓取任务推送”,
Body = new BodyBuilder
{
HtmlBody = $“本次抓取到{hotNews.Count()}条数据,时间:{DateTime.Now:yyyy-MM-dd HH:mm:ss}”
}.ToMessageBody()
};
await EmailHelper.SendAsync(message);

分别在两个爬虫脚本中添加发送Email,MimeMessage中设置了邮件主题Subject,正文Body,最后调用await EmailHelper.SendAsync(message)执行发送邮件操作。

编译运转执行两个定时任务,看看能否收到邮件提示。

3

胜利了,邮箱收到了两条提示。

还有一种比拟特殊的用法,也引见一下,假如想要发送带图片的邮件怎样操作呢?留意不是附件,是将图片内嵌在邮箱中。

普通常规都是有邮件模板的,将图片的详细地址插入到img标签中,这就不说了,这里选择另外一种方式。以前面添加的PuppeteerTestJob为例,正好我们生成了一张图片的。将这种图片以邮件的方式发进来。


public class PuppeteerTestJob : IBackgroundJob
{
public async Task ExecuteAsync()
{
var path = Path.Combine(Path.GetTempPath(), “meowv.png”);

    ...
    
    await page.ScreenshotAsync(path, new ScreenshotOptions
    {
        FullPage = true,
        Type = ScreenshotType.Png
    });
    // 发送带图片的Email
    var builder = new BodyBuilder();
    var image = builder.LinkedResources.Add(path);
    image.ContentId = MimeUtils.GenerateMessageId();
    builder.HtmlBody = "当前时间:{0}.".FormatWith(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), image.ContentId);
    var message = new MimeMessage
    {
        Subject = "【定时任务】每日热点数据抓取任务推送",
        Body = builder.ToMessageBody()
    };
    await EmailHelper.SendAsync(message);
}

}
先肯定我们生成图片的途径 path ,将图片生成Message-Id,然后赋值给ContentId,给模板中图片标签cid赋上值在调用发送邮件办法即可。

你可能感兴趣的:(诺禾、abp vNext 和 .NET Core 开发博客项目)