当前位置: 首页 > wzjs >正文

angeljs做的网站seo引擎搜索网站关键词

angeljs做的网站,seo引擎搜索网站关键词,wordpress设置标题大小,云南专业网站建站建设截取网页截图看似是一项简单的任务,但当你真正动手去做的时候,就会发现事情远没有那么容易。我在尝试截取一篇很长的 Reddit 帖子时就深有体会。一开始我以为只要调用 browser.TakeImage() 就万事大吉,结果却陷入了浏览器视口、动态内容加载、…

截取网页截图看似是一项简单的任务,但当你真正动手去做的时候,就会发现事情远没有那么容易。我在尝试截取一篇很长的 Reddit 帖子时就深有体会。一开始我以为只要调用 browser.TakeImage() 就万事大吉,结果却陷入了浏览器视口、动态内容加载、内存占用等一系列问题。

在这篇文章中,我将分享从一开始的“想当然”到最后找到高效方案的全过程。我们将以 r/dotnet 子版块为案例,探索常见的陷阱以及如何避免这些问题。看完这篇文章后,你将掌握如何稳定、完整地截取包含动态内容与无限滚动的网页截图的方法。

基础截图方式

我们先从最基础的方法开始:不进行任何特殊处理,直接截取截图。在 DotNetBrowser 中,这非常简单:

var image = browser.TakeImage();
var bitmap = ToBitmap(image);
bitmap.Save("screenshot.png", ImageFormat.Png);

由于 DotNetBrowser 返回的是原始位图,我们需要一个工具方法将其转换为 System.Drawing.Bitmap ,以便进行标准的 .NET 操作:

public static Bitmap ToBitmap(DotNetBrowser.Ui.Bitmap bitmap)
{var width = (int)bitmap.Size.Width;var height = (int)bitmap.Size.Height;var data = bitmap.Pixels.ToArray();var bmp = new Bitmap(width, height, PixelFormat.Format32bppRgb);var bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height),ImageLockMode.WriteOnly, bmp.PixelFormat);Marshal.Copy(data, 0, bmpData.Scan0, data.Length);bmp.UnlockBits(bmpData);return bmp;
}

运行这段代码后,我们得到了第一张截图:

使用 DotNetBrowser 制作的简单屏幕截图

使用 [DotNetBrowser](https://teamdev.cn/dotnetbrowser/?utm_source=csdn&utm_medium=article&utm_campaign=taking-screenshots-of-web-pages) 制作的简单屏幕截图

但问题显而易见:我们只截取了页面的一小部分。

这是因为 TakeImage() 方法仅截取浏览器视口内可见的内容,而默认视口大小并不足以显示整个页面。

截取整页截图

我们需要先获取网页的尺寸,并将浏览器调整为相应大小,然后重新尝试截图。可以通过 JavaScript 获取页面的尺寸,方法是取 documentdocument.documentElement 中较大的那个值:

var widthScript = @"Math.max(document.body.scrollWidth,document.documentElement.scrollWidth)";var heightScript = @"Math.max(document.body.scrollHeight,document.documentElement.scrollHeight)";

然后调整浏览器大小以匹配这些尺寸:

var frame = browser.MainFrame;
var width = frame.ExecuteJavaScript<double>(widthScript).Result;
var height = frame.ExecuteJavaScript<double>(heightScript).Result;browser.Size = new Size((uint)width, (uint)height);
var image = browser.TakeImage();

以下是使用这种改进方法得到的结果:

截图区域变大了,但内容尚未加载完成

截图区域变大了,但内容尚未加载完成。

查看完整图片

紧接着出现了另一个问题:页面并未完全加载。这是因为我们在调整浏览器大小后立即进行了截图,没有给浏览器足够的时间来加载和渲染所有内容。从页面底部的加载指示器可以看出这一点。

让我们填加一个暂停等待时间:

browser.Size = new Size((uint)width, (uint)height);
// 通过反复试验得出的任意数字。
Thread.Sleep(2000);
var image = browser.TakeImage();

再试一次:

包含所有内容的完整截图

包含所有内容的完整截图

查看完整图片

终于,我们得到了一张像样的截图!但位图对象变得相当大,而且 Chromium 需要大量资源来渲染大视口,这在实际应用中并不实用。我们可以做得更好。

截取分段截图

使用之前的方法,浏览器会一次性渲染整个页面,并将结果位图传递给 .NET 进程内存。在处理长页面时,这会迅速耗尽系统资源,尤其是 RAM。

与其尝试一次性截取整个页面,不如我们将其分解为更小、更易管理的部分:

  1. 对页面的各个小段进行多次截图。
  2. 在每次截取之间滚动屏幕。
  3. 将各个部分拼接成最终图像。

以下是实现这种方法的代码:

// Reddit 页面是无限滚动的,因此我们需要设置一个固定的截图次数。
var numberOfShots = 15;
var viewportHeight = 1000;
browser.Size = new Size((uint)Width, (uint)viewportHeight);var capturedHeight = 0;
for (var count = 0; count < numberOfShots; count++)
{capturedHeight += viewportHeight;frame.ExecuteJavaScript($"window.scrollTo(0, {capturedHeight})").Wait();// 为了等待内容加载而设定的任意暂停时间。Thread.Sleep(500);var image = browser.TakeImage();var bitmap = ToBitmap(image);bitmap.Save($"screenshot-{count:D3}.png", ImageFormat.Png);
}

在实际应用中,我们会在另一台服务器上的异步任务中拼接这些片段。但为了简单起见,我们选择直接使用这个辅助函数:

public static Bitmap MergeBitmapsVertically(List<Bitmap> bitmaps)var files = Directory.GetFiles("/path/to/directory", "*.png").OrderBy(Path.GetFileName).ToArray();var images = files.Select(f => Image.FromFile(f)).ToArray();int width = images.Max(img => img.Width);int totalHeight = images.Sum(img => img.Height);using var merged = new Bitmap(width, totalHeight);using (var g = Graphics.FromImage(final)){int y = 0;foreach (var img in images){g.DrawImage(img, 0, y);y += img.Height;}}merged.Save("merged.png");
}

让我们看看结果如何:

合并后的截图片段包含重复元素

合并后的截图片段包含重复元素

查看完整图片

又一个新问题出现了:页眉和导航侧边栏在每张分段截图里重复出现,这显然不是截图应有的样子!

处理固定元素

当我们滚动页面时,像页眉和侧边栏这样的固定元素会保持在原位不动。但在进行分段截图时,我们希望这些固定元素只出现在第一段截图中。

让我们通过 CSS 的 position 属性来找出这些元素,并将它们隐藏起来:

var removeFixedElements = @"(() => {document.querySelectorAll('*').forEach(el => {const pos = getComputedStyle(el).position;if (pos === 'fixed' || pos === 'sticky') {el.style.display = 'none';}});})()";for (var count = 0; count < numberOfShots; count++)
{// 仅从第二张截图开始移除固定元素,// 这样可以保留第一张截图中的页眉和导航栏。if (count == 1) {frame.ExecuteJavaScript(removeFixedElements).Wait();}// 继续进行截图操作。
}

另一个常见的固定元素是 Cookie 同意弹窗。由于每个网站的实现方式都不一样,我们需要逐个页面单独处理。

以 Reddit 为例,我们可以使用以下代码识别并隐藏 Cookie 弹窗:

var removeCookieScreen =@"(() => {const dialog = document.querySelector('reddit-cookie-banner');if (dialog) {dialog.style.display = 'none';}})()";
frame.ExecuteJavaScript(removeCookieScreen).Wait();

最终,我们以节省内存的方式截取了一张合适的网页截图。

一张干净、完整的网页截图

一张干净、完整的网页截图

查看完整图片

总结

最初只是一个简单的 browser.TakeImage() 调用,最后演变成一个需要应对无数细节的复杂解决方案。我们解决了以下挑战:

  • 一次性截取整页内容;
  • 将长页面分段截取并拼接;
  • 处理固定元素和 Cookie 弹窗;
  • 优化内存使用和实用性。

需要说明的是,本文介绍的方法并非放之四海而皆准。每个网页都有其独特之处,而优秀的截图工具之所以强大,正是因为它能处理各种边缘场景。尽管如此,本文所展示的方法已经涵盖了使用 DotNetBrowser 进行网页截图所需掌握的所有核心知识。

http://www.dtcms.com/wzjs/488482.html

相关文章:

  • 济宁百度网站建设百度地图导航2022最新版下载
  • 金科做的网站网络营销专业学校排名
  • 做淘宝客的的网站有什么要求吗新网站应该怎么做seo
  • 酒泉网站建设平台企业宣传册模板
  • 网站建站视频教程seo人才招聘
  • 海南在线人才网招聘官网seo优化软件大全
  • 外贸出口工艺品怎么做外贸网站东莞做网站seo
  • 网站建设公司响应式网站模板互联网推广软件
  • 快速做网站联系电话网站建设一般多少钱
  • 冒用公司名义做网站app拉新任务平台
  • 沧州1 1 网站建设网络营销swot分析
  • 公司在线起名免费网百度seo关键词排名
  • wordpress 访问路径今日头条搜索优化怎么做
  • 吉林省住房建设厅网站网址大全百度
  • 建设工程消防监督管理规定网站杭州网站优化
  • 可以做英文纵横字谜的网站长春seo网站管理
  • 网站建设能在家工作上海空气中检测出病毒
  • wordpress用户上传视频教程北京网站建设优化
  • 武汉做网站专业建站环球网疫情最新动态
  • 可做产品预售的网站免费网站怎么注册
  • 清河网站建设费用seo快速排名软件
  • 有中文网站 怎么做英文网站推广公司简介
  • 音乐网站怎么做无线增值业务如何在百度上发表文章
  • 51单片机可以做网站销售推广
  • 信息平台网站的建设 文档seo搜索引擎优化课程总结
  • wordpress采集 知乎做灰色词seo靠谱
  • 可以写代码的网站app推广方案范例
  • 不拦截网站的浏览器株洲seo排名
  • 精美 企业网站模板竞价账户
  • 做视频编辑哪个网站素材比较好网络营销的模式有哪些?