现在大多数网站都是随着滚动条的滑动加载页面内容的,因此单纯获得静态页面的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

  1. ChromeDriver driver = new ChromeDriver();
  2. driver.Navigate().GoToUrl(url);
  3. string title = driver.Title;//页面title
  4. string html = driver.PageSource;//页面Html

不启动Chrome窗口及关闭Chrome控制台获取网页

程序执行时会自动打开Chrome窗口和输出控制台中一些信息,我们不需要这些东西。

  1. //不启动chrome窗口
  2. ChromeOptions options = new ChromeOptions();
  3. options.AddArgument("headless");
  4. //关闭ChromeDriver控制台
  5. ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
  6. driverService.HideCommandPromptWindow = true;
  7. ChromeDriver driver = new ChromeDriver(driverService, options);
  8. driver.Navigate().GoToUrl(url);

将页面滚动到底部

如果使用scrollTo(0, document.body.scrollHeight),直接让将页面滚动到底部会导致页面中间部分读取失败,所以需要分几次滑动并且给页面足够的时间加载

  1. for (int i = 1; i <= 10; i++)
  2. {
  3. string jsCode = "window.scrollTo({top: document.body.scrollHeight / 10 * " + i + ", behavior: \"smooth\"});";
  4. //使用IJavaScriptExecutor接口运行js代码
  5. IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
  6. js.ExecuteScript(jsCode);
  7. //暂停滚动
  8. Thread.Sleep(1000);
  9. }

使用HtmlAgilityPack解析读取到的Html

以下内容与上一篇文章基本相同

  1. string title = driver.Title;//页面title
  2. string html = driver.PageSource;//页面Html
  3. HtmlDocument doc = new HtmlDocument();
  4. doc.LoadHtml(html);//解析Html字符串
  5. string imgPath = "//img";//选择img
  6. //获取img标签中的图片
  7. foreach (HtmlNode node in doc.DocumentNode.SelectNodes(imgPath))
  8. {
  9. ······
  10. }

完整代码

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Net;
  7. using System.IO;
  8. using HtmlAgilityPack;
  9. using System.Text.RegularExpressions;
  10. using OpenQA.Selenium;
  11. using OpenQA.Selenium.Chrome;
  12. using System.Threading;
  13. namespace WebCrawlerDemo
  14. {
  15. class Program
  16. {
  17. static void Main(string[] args)
  18. {
  19. WebClient wc = new WebClient();
  20. int imgNum = 0;//图片编号
  21. string url = "https://www.bilibili.com";
  22. string html = FinalHtml.GetFinalHtml(url, 10);
  23. HtmlDocument doc = new HtmlDocument();
  24. doc.LoadHtml(html);
  25. string imgPath = "//img";//选择img
  26. //HtmlNode nodes = hd.DocumentNode.SelectSingleNode(path);
  27. //获取img标签中的图片
  28. foreach (HtmlNode node in doc.DocumentNode.SelectNodes(imgPath))
  29. {
  30. if (node.Attributes["src"] != null)
  31. {
  32. string imgUrl = node.Attributes["src"].Value.ToString();
  33. if (imgUrl != "" && imgUrl != " ")
  34. {
  35. imgNum++;
  36. //生成文件名,自动获取后缀
  37. string fileName = GetImgName(imgUrl, imgNum);
  38. //Console.WriteLine(fileName);
  39. //Console.WriteLine(imgUrl);
  40. ImgDownloader.DownloadImg(wc, imgUrl, "images/", fileName);
  41. }
  42. }
  43. }
  44. //获取背景图
  45. string bgImgPath = "//*[@style]";//选择具有style属性的节点
  46. foreach (HtmlNode node in doc.DocumentNode.SelectNodes(bgImgPath))
  47. {
  48. if (node.Attributes["style"].Value.Contains("background-image:url"))
  49. {
  50. imgNum++;
  51. string bgImgUrl = node.Attributes["style"].Value;
  52. bgImgUrl = Regex.Match(bgImgUrl, @"(?<=\().+?(?=\))").Value;//读取url()的内容
  53. //Console.WriteLine(bgImgUrl);
  54. //生成文件名,自动获取后缀
  55. string fileName = GetImgName(bgImgUrl, imgNum);
  56. ImgDownloader.DownloadImg(wc, bgImgUrl, "images/bgcImg/", fileName);
  57. }
  58. }
  59. Console.WriteLine("----------END----------");
  60. Console.WriteLine($"一共获得: {imgNum}张图");
  61. Console.ReadKey();
  62. }
  63. }
  64. /// <summary>
  65. /// 图片下载器
  66. /// </summary>
  67. public class ImgDownloader
  68. {
  69. /// <summary>
  70. /// 下载图片
  71. /// </summary>
  72. /// <param name="webClient"></param>
  73. /// <param name="url">图片url</param>
  74. /// <param name="folderPath">文件夹路径</param>
  75. /// <param name="fileName">图片名</param>
  76. public static void DownloadImg(WebClient webClient, string url, string folderPath, string fileName)
  77. {
  78. //如果文件夹不存在,则创建一个
  79. if (!Directory.Exists(folderPath))
  80. {
  81. Directory.CreateDirectory(folderPath);
  82. }
  83. //判断路径是否完整,补全不完整的路径
  84. if (url.IndexOf("https:") == -1 && url.IndexOf("http:") == -1)
  85. {
  86. url = "https:" + url;
  87. }
  88. //下载图片
  89. try
  90. {
  91. webClient.DownloadFile(url, folderPath + fileName);
  92. Console.WriteLine(fileName + "下载成功");
  93. }
  94. catch (Exception ex)
  95. {
  96. Console.Write(ex.Message);
  97. Console.WriteLine(url);
  98. }
  99. }
  100. /// <summary>
  101. /// 生成图片名称
  102. /// </summary>
  103. /// <param name="imageUrl">图片地址</param>
  104. /// <param name="imageNum">图片编号</param>
  105. /// <returns></returns>
  106. public static string GetImgName(string imageUrl, int imageNum)
  107. {
  108. string imgExtension;
  109. if (imageUrl.LastIndexOf(".") != -1)
  110. {
  111. imgExtension = imageUrl.Substring(imageUrl.LastIndexOf("."));
  112. }
  113. else
  114. {
  115. imgExtension = ".jpg";
  116. }
  117. return imageNum + imgExtension;
  118. }
  119. }
  120. /// <summary>
  121. /// 获得执行过js的网址
  122. /// </summary>
  123. public class FinalHtml
  124. {
  125. /// <summary>
  126. /// 获得拉动滚动条后的页面
  127. /// </summary>
  128. /// <param name="url">网址</param>
  129. /// <param name="sectionNum">滚动几次</param>
  130. /// <returns>html字符串</returns>
  131. public static string GetFinalHtml(string url, int sectionNum)
  132. {
  133. //不启动chrome窗口
  134. ChromeOptions options = new ChromeOptions();
  135. options.AddArgument("headless");
  136. //关闭ChromeDriver控制台
  137. ChromeDriverService driverService = ChromeDriverService.CreateDefaultService();
  138. driverService.HideCommandPromptWindow = true;
  139. ChromeDriver driver = new ChromeDriver(driverService, options);
  140. driver.Navigate().GoToUrl(url);
  141. string title = driver.Title;
  142. Console.WriteLine($"Title: {title}");
  143. //将页面滚动到底部
  144. Console.Write("页面滚动中,请稍后");
  145. for (int i = 1; i <= sectionNum; i++)
  146. {
  147. string jsCode = "window.scrollTo({top: document.body.scrollHeight / " + sectionNum + " * " + i + ", behavior: \"smooth\"});";
  148. IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
  149. js.ExecuteScript(jsCode);
  150. Console.Write(".");
  151. Thread.Sleep(1000);
  152. }
  153. Console.WriteLine();
  154. string html = driver.PageSource;
  155. driver.Quit();
  156. return html;
  157. }
  158. }
  159. }

参考文章

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. mysql sqrt() 函数

    mysql> ); +----------+ | sqrt() | +----------+ | | +----------+ row in set (0.00 sec)

  2. edusoho上传视频弹出abort之解决方案

    错误描述:edusoho上传如avi.mp4等容量大的图片(如100m以上或500m等)弹出abort提示框 原因:是因为web服务器apache默认上传文件有限制导致的 解决办法如下: (1)首先修 ...

  3. 【大数据】安装关系型数据库MySQL 安装大数据处理框架Hadoop

    作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/3161 1.安装Mysql 使用命令  sudo apt-get ins ...

  4. python 玩爬虫安装了一大堆第三方库

    之前就听说过爬虫,感觉很复杂的样子,但是看到python代码很简短.由于本机已经安装了python2.7 所以就拿来py 文件跑一下想看看效果. 结果各种代码错误.然后根据每个错误去下载对应的依赖项. ...

  5. 工具系列 | 使用Lodop进行WEB打印程序开发

    Lodop(标音:劳道谱,俗称:露肚皮)是专业WEB控件,用它既可裁剪输出页面内容,又可用程序代码直接实现 复杂打印.控件功能强大,却简单易用,所有调用如同JavaScript扩展语句. WEB套打可 ...

  6. 012 spring retry重试原理的解析

    有点复杂,在后续的章节,将会对其中涉及到的知识点,再分章节进行说明. 1.程序结构 2.@Retryable package com.jun.web.annotation.theory; import ...

  7. UltraEdit 的“查看方式”着色类项型

    UltraEdit 的“查看方式”着色类项型 2011年06月22日 13:16:00 cnki_ok 阅读数 5722   版权声明:本文为博主原创文章,遵循CC 4.0 by-sa版权协议,转载请 ...

  8. BackgroundWorkerHelper

    public static class BackgroundWorkerHelper { public static void Run(DoWorkEventHandler doWork, RunWo ...

  9. C# Newtonsoft.Json解析json字符串处理(最清晰易懂的方法)

    需求: 假设有如下json字符串: { ", "employees": [ { "firstName": "Bill", &quo ...

  10. 使用协方差矩阵的特征向量PCA来处理数据降维

    取2维特征,方便图形展示 import matplotlib.pyplot as plt from sklearn.decomposition import PCA from sklearn.data ...