现在大多数网站都是随着滚动条的滑动加载页面内容的,因此单纯获得静态页面的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爬取需要拉动滚动条的页面内容的更多相关文章

  1. HtmlUnit爬取Ajax动态生成的页面内容

    HtmlUnit说白了就是一个浏览器,这个浏览器是用Java写的无界面的浏览器,正因为其没有界面,因此执行的速度还是可以滴. HtmlUnit提供了一系列的API,这些API可以干的功能比较多,如表单 ...

  2. selenium模块使用详解、打码平台使用、xpath使用、使用selenium爬取京东商品信息、scrapy框架介绍与安装

    今日内容概要 selenium的使用 打码平台使用 xpath使用 爬取京东商品信息 scrapy 介绍和安装 内容详细 1.selenium模块的使用 # 之前咱们学requests,可以发送htt ...

  3. [Python爬虫] Selenium爬取新浪微博客户端用户信息、热点话题及评论 (上)

    转载自:http://blog.csdn.net/eastmount/article/details/51231852 一. 文章介绍 源码下载地址:http://download.csdn.net/ ...

  4. selenium爬取煎蛋网

    selenium爬取煎蛋网 直接上代码 from selenium import webdriver from selenium.webdriver.support.ui import WebDriv ...

  5. 利用selenium爬取京东商品信息存放到mongodb

    利用selenium爬取京东商城的商品信息思路: 1.首先进入京东的搜索页面,分析搜索页面信息可以得到路由结构 2.根据页面信息可以看到京东在搜索页面使用了懒加载,所以为了解决这个问题,使用递归.等待 ...

  6. 利用Selenium爬取淘宝商品信息

    一.  Selenium和PhantomJS介绍 Selenium是一个用于Web应用程序测试的工具,Selenium直接运行在浏览器中,就像真正的用户在操作一样.由于这个性质,Selenium也是一 ...

  7. Scrapy 框架 使用 selenium 爬取动态加载内容

    使用 selenium 爬取动态加载内容 开启中间件 DOWNLOADER_MIDDLEWARES = { 'wangyiPro.middlewares.WangyiproDownloaderMidd ...

  8. 使用selenium爬取网站动态数据

    处理页面动态加载的爬取 selenium selenium是python的一个第三方库,可以实现让浏览器完成自动化的操作,比如说点击按钮拖动滚轮等 环境搭建: 安装:pip install selen ...

  9. scrapy框架 + selenium 爬取豆瓣电影top250......

    废话不说,直接上代码..... 目录结构 items.py import scrapy class DoubanCrawlerItem(scrapy.Item): # 电影名称 movieName = ...

随机推荐

  1. hadoop综合

    对CSV文件进行预处理生成无标题文本文件,将爬虫大作业产生的csv文件上传到HDFS 首先,我们需要在本地中创建一个/usr/local/bigdatacase/dataset文件夹,具体的步骤为: ...

  2. 【软工实践】Alpha冲刺(5/6)

    链接部分 队名:女生都队 组长博客: 博客链接 作业博客:博客链接 小组内容 恩泽(组长) 过去两天完成了哪些任务 描述 任务界面设计,任务功能后端实现 任务计时功能及界面实现 展示GitHub代码签 ...

  3. IDEA查看接口的实现类

    查找接口的实现类: 快捷键 ctrl + alt +B 再按F2查看详细文档注解 查看类或接口的继承关系: ctrl + h

  4. 两种Redis持久化原理的详解

    Redis为持久化提供了两种方式: RDB:在指定的时间间隔能对你的数据进行快照存储. AOF:记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据. 本文将通过下面内容的介 ...

  5. node.js生成验证码及图片

    示例代码: var svgCaptcha = require('svg-captcha'); var fs = require('fs'); var codeConfig = { size: 5,// ...

  6. [LeetCode] 6. ZigZag Converesion 之字型转换字符串

    The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like ...

  7. [LeetCode] 380. Insert Delete GetRandom O(1) 插入删除获得随机数O(1)时间

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  8. TIBCO Jaspersoft Studio 报表软件使用教程

    Detail 1里面放置动态内容框可以循环遍历数据 版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn ...

  9. 使用vue开发微信公众号,解决微信缓存

    1.页面加入标红的代码,让页面不缓存 <!DOCTYPE html> <html manifest="IGNORE.manifest"> <head& ...

  10. javaScript Es6数组与对象的实例方法

     个人心得 我们在没有接触Es6方法之前,做一些算法之类的事情是就比较麻烦,在做的过程中也要考虑很多的问题,比较麻烦,而Es6的方法正是来方便我们在平常运用时能够将问题简便化,大大的减少我们的日常代码 ...