C# HtmlAgilityPack+Selenium爬取需要拉动滚动条的页面内容
现在大多数网站都是随着滚动条的滑动加载页面内容的,因此单纯获得静态页面的Html是无法获得全部的页面内容的。使用Selenium就可以模拟浏览器拉动滑动条来加载所有页面内容。
前情提要
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",分别安装:
- Selenium.WebDriver
- Selenium.Chrome.WebDriver
实例(获取某网站主页所有图片)
普通获取网页Html
ChromeDriver driver = new ChromeDriver();
driver.Navigate().GoToUrl(url);
string title = driver.Title;//页面title
string 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;//页面title
string html = driver.PageSource;//页面Html
HtmlDocument 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;
}
}
}
参考文章
C# HtmlAgilityPack+Selenium爬取需要拉动滚动条的页面内容的更多相关文章
- HtmlUnit爬取Ajax动态生成的页面内容
HtmlUnit说白了就是一个浏览器,这个浏览器是用Java写的无界面的浏览器,正因为其没有界面,因此执行的速度还是可以滴. HtmlUnit提供了一系列的API,这些API可以干的功能比较多,如表单 ...
- selenium模块使用详解、打码平台使用、xpath使用、使用selenium爬取京东商品信息、scrapy框架介绍与安装
今日内容概要 selenium的使用 打码平台使用 xpath使用 爬取京东商品信息 scrapy 介绍和安装 内容详细 1.selenium模块的使用 # 之前咱们学requests,可以发送htt ...
- [Python爬虫] Selenium爬取新浪微博客户端用户信息、热点话题及评论 (上)
转载自:http://blog.csdn.net/eastmount/article/details/51231852 一. 文章介绍 源码下载地址:http://download.csdn.net/ ...
- selenium爬取煎蛋网
selenium爬取煎蛋网 直接上代码 from selenium import webdriver from selenium.webdriver.support.ui import WebDriv ...
- 利用selenium爬取京东商品信息存放到mongodb
利用selenium爬取京东商城的商品信息思路: 1.首先进入京东的搜索页面,分析搜索页面信息可以得到路由结构 2.根据页面信息可以看到京东在搜索页面使用了懒加载,所以为了解决这个问题,使用递归.等待 ...
- 利用Selenium爬取淘宝商品信息
一. Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样.由于这个性质,Selenium也是一 ...
- Scrapy 框架 使用 selenium 爬取动态加载内容
使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ...
- 使用selenium爬取网站动态数据
处理页面动态加载的爬取 selenium selenium是python的一个第三方库,可以实现让浏览器完成自动化的操作,比如说点击按钮拖动滚轮等 环境搭建: 安装:pip install selen ...
- scrapy框架 + selenium 爬取豆瓣电影top250......
废话不说,直接上代码..... 目录结构 items.py import scrapy class DoubanCrawlerItem(scrapy.Item): # 电影名称 movieName = ...
随机推荐
- React中兄弟组件传值
兄弟组件传值 实际上是间接的通过第三方来实现传值,举例,第一个儿子把值传给父亲,父亲在把这个值传给第二个儿子,这样就实现了兄弟组件传值 来看代码: 父组件代码 import React from 'r ...
- 【Qt开发】vs2017+qt5.x编译32位应用
概述 最近有同学私信我,问如何使用vs2017+qt5.10编译出32位的应用,需要使用msvc2017_x86的插件,然而qt官网并没有提供,只能使用源码编译生成msvc2017_x86插件,使用n ...
- 自动化远程部署shell脚本
历史原因,有一段时间,项目开发采用一种模式:项目开发及代码版本管理在外网,而主要测试在内网.所以为了同步开发进度,每天会将所有服务在外网jenkins上打包好,然后将服务jar包拷进内网,由于内网服务 ...
- CEF 访问需要认证网页或接口(在Request的Headers中添加认证Token)
转载:https://blog.csdn.net/wdw984/article/details/85275289 1.首先要让我们自己的CefClient这个类公有继承CefRequestHandle ...
- ASP.NET中httpmodules与httphandlers全解析
https://www.cnblogs.com/zpc870921/archive/2012/03/12/2391424.html https://www.cnblogs.com/PiaoMiaoGo ...
- PAT 甲级 1086 Tree Traversals Again (25分)(先序中序链表建树,求后序)***重点复习
1086 Tree Traversals Again (25分) An inorder binary tree traversal can be implemented in a non-recu ...
- [LeetCode] 62. Unique Paths 唯一路径
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below). The ...
- 主机可以ping通虚拟机,虚拟机ping不通主机和外网
vmware-->编辑-->虚拟网络编辑器-->更改配置,如下图选择:
- 【编程开发】x86,I386,i686, x86_64, x64,amd64、Windows Linux AIX下查看CPU位数和操作系统位数、rpm包名
a2ps-4.13b-57.2.el5.i386.rpm 每一个rpm包的名称都由"-"和"."分成了若干部分.就拿 a2ps-4.13b-57.2.el5.i ...
- svn客户端清空账号信息的两种方法
1.直接删除配置 C:\Users\Administrator\AppData\Roaming\Subversion\auth 一般在这个文件夹下 2.svn的设置里清空