现在大多数网站都是随着滚动条的滑动加载页面内容的,因此单纯获得静态页面的HTML是无法获得全部的页面内容的。使用Selenium就可以模拟浏览器拉动滑动条来加载所有页面内容。
前情提要C#HtmlAgilityPack爬取静态页面Selenium简介Selenium是一个WEB自动化测试工具。Selenium测试直接运行在浏览器中,就像真正的用户在 *** 作一样。支持的浏览器包括IE(7,8,9,10,11),Mozilla firefox,Safari,Google Chrome,Opera等。主要功能包括:测试与浏览器的兼容性——测试你的应用程序看是否能够很好得工作在不同浏览器和 *** 作系统之上。测试系统功能——创建回归测试检验软件功能和用户需求。支持自动录制动作和自动生成 .Net、Java、Perl等不同语言的测试脚本。Selenium也是一款同样使用Apache license 2.0协议发布的开源框架。
C#安装Selenium本文仅仅是使用Selenium实现拉动滚动条的功能,所以不对Selenium进行过多的介绍。
通过Nuget包管理器搜索"Selenium",分别安装:
ChromeDriver driver = new ChromeDriver();driver.Navigate().GoToUrl(url);string Title = driver.Title;//页面Titlestring HTML = driver.PageSource;//页面HTML
不启动Chrome窗口及关闭Chrome控制台获取网页程序执行时会自动打开Chrome窗口和输出控制台中一些信息,我们不需要这些东西。
//不启动Chrome窗口ChromeOptions options = new ChromeOptions();options.AddArgument("headless");//关闭ChromeDriver控制台ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();driverService.HIDeCommandPromptwindow = true;ChromeDriver driver = new ChromeDriver(driverService,options);driver.Navigate().GoToUrl(url);
将页面滚动到底部如果使用scrollTo(0,document.body.scrollHeight)
,直接让将页面滚动到底部会导致页面中间部分读取失败,所以需要分几次滑动并且给页面足够的时间加载
for (int i = 1; i <= 10; i++){ string JsCode = "window.scrollTo({top: document.body.scrollHeight / 10 * " + i + ",behavior: \"smooth\"});"; //使用IJavaScriptExecutor接口运行Js代码 IJavaScriptExecutor Js = (IJavaScriptExecutor)driver; Js.ExecuteScript(JsCode); //暂停滚动 Thread.Sleep(1000);}
使用HTMLAgilityPack解析读取到的HTML以下内容与上一篇文章基本相同
string Title = driver.Title;//页面Titlestring HTML = driver.PageSource;//页面HTMLHTMLdocument doc = new HTMLdocument();doc.LoadHTML(HTML);//解析HTML字符串string imgPath = "//img";//选择img//获取img标签中的图片foreach (HTMLNode node in doc.documentNode.SelectNodes(imgPath)){ ······}
完整代码using System;using System.Collections.Generic;using System.linq;using System.Text;using System.Threading.Tasks;using System.Net;using System.IO;using HTMLAgilityPack;using System.Text.RegularExpressions;using OpenQA.Selenium;using OpenQA.Selenium.Chrome;using System.Threading;namespace WebCrawlerDemo{ class Program { static voID Main(string[] args) { WebClIEnt wc = new WebClIEnt(); int imgNum = 0;//图片编号 string url = "https://www.bilibili.com"; string HTML = FinalHTML.GetFinalHTML(url,10); HTMLdocument doc = new HTMLdocument(); doc.LoadHTML(HTML); string imgPath = "//img";//选择img //HTMLNode nodes = hd.documentNode.SelectSingleNode(path); //获取img标签中的图片 foreach (HTMLNode node in doc.documentNode.SelectNodes(imgPath)) { if (node.Attributes["src"] != null) { string imgurl = node.Attributes["src"].Value.ToString(); if (imgurl != "" && imgurl != " ") { imgNum++; //生成文件名,自动获取后缀 string filename = Getimgname(imgurl,imgNum); //Console.Writeline(filename); //Console.Writeline(imgurl); imgDownloader.Downloadimg(wc,imgurl,"images/",filename); } } } //获取背景图 string bgimgPath = "//*[@style]";//选择具有style属性的节点 foreach (HTMLNode node in doc.documentNode.SelectNodes(bgimgPath)) { if (node.Attributes["style"].Value.Contains("background-image:url")) { imgNum++; string bgimgurl = node.Attributes["style"].Value; bgimgurl = Regex.Match(bgimgurl,@"(?<=\().+?(?=\))").Value;//读取url()的内容 //Console.Writeline(bgimgurl); //生成文件名,自动获取后缀 string filename = Getimgname(bgimgurl,imgNum); imgDownloader.Downloadimg(wc,bgimgurl,"images/bgcimg/",filename); } } Console.Writeline("----------END----------"); Console.Writeline($"一共获得: {imgNum}张图"); Console.ReadKey(); } } /// <summary> /// 图片下载器 /// </summary> public class imgDownloader { /// <summary> /// 下载图片 /// </summary> /// <param name="webClIEnt"></param> /// <param name="url">图片url</param> /// <param name="folderPath">文件夹路径</param> /// <param name="filename">图片名</param> public static voID Downloadimg(WebClIEnt webClIEnt,string url,string folderPath,string filename) { //如果文件夹不存在,则创建一个 if (!Directory.Exists(folderPath)) { Directory.CreateDirectory(folderPath); } //判断路径是否完整,补全不完整的路径 if (url.IndexOf("https:") == -1 && url.IndexOf("http:") == -1) { url = "https:" + url; } //下载图片 try { webClIEnt.Downloadfile(url,folderPath + filename); Console.Writeline(filename + "下载成功"); } catch (Exception ex) { Console.Write(ex.Message); Console.Writeline(url); } } /// <summary> /// 生成图片名称 /// </summary> /// <param name="imageUrl">图片地址</param> /// <param name="imageNum">图片编号</param> /// <returns></returns> public static string Getimgname(string imageUrl,int imageNum) { string imgExtension; if (imageUrl.LastIndexOf(".") != -1) { imgExtension = imageUrl.Substring(imageUrl.LastIndexOf(".")); } else { imgExtension = ".jpg"; } return imageNum + imgExtension; } } /// <summary> /// 获得执行过Js的网址 /// </summary> public class FinalHTML { /// <summary> /// 获得拉动滚动条后的页面 /// </summary> /// <param name="url">网址</param> /// <param name="sectionNum">滚动几次</param> /// <returns>HTML字符串</returns> public static string GetFinalHTML(string url,int sectionNum) { //不启动Chrome窗口 ChromeOptions options = new ChromeOptions(); options.AddArgument("headless"); //关闭ChromeDriver控制台 ChromeDriverService driverService = ChromeDriverService.CreateDefaultService(); driverService.HIDeCommandPromptwindow = true; ChromeDriver driver = new ChromeDriver(driverService,options); driver.Navigate().GoToUrl(url); string Title = driver.Title; Console.Writeline($"Title: {Title}"); //将页面滚动到底部 Console.Write("页面滚动中,请稍后"); for (int i = 1; i <= sectionNum; i++) { string JsCode = "window.scrollTo({top: document.body.scrollHeight / " + sectionNum + " * " + i + ",behavior: \"smooth\"});"; IJavaScriptExecutor Js = (IJavaScriptExecutor)driver; Js.ExecuteScript(JsCode); Console.Write("."); Thread.Sleep(1000); } Console.Writeline(); string HTML = driver.PageSource; driver.Quit(); return HTML; } }}
参考文章Selenium爬取网页实战 总结 以上是内存溢出为你收集整理的C# HtmlAgilityPack+Selenium爬取需要拉动滚动条的页面内容全部内容,希望文章能够帮你解决C# HtmlAgilityPack+Selenium爬取需要拉动滚动条的页面内容所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)