C#爬取动态网页上的信息:B站主页
简介
动态内容网站使用 JavaScript 脚本动态检索和渲染数据,爬取信息时需要模拟浏览器行为,否则获取到的源码基本是空的。爬取步骤如下:
- 使用 Selenium 获取渲染后的 HTML 文档
- 使用 HtmlAgilityPack 解析 HTML 文档
新建项目,安装需要的库:
- Selenium.WebDriver
- HtmlAgilityPack
获取 HTML 文档
需要注意的主要是以下2点:
- 设置浏览器启动参数:无头模式、禁用GPU加速、设置启动时窗口大小
- 等待页面动态加载完成:等待5秒钟,设置一个合适的时间即可
private static string GetHtml(string url)
{
ChromeOptions options = new ChromeOptions();
// 不显示浏览器
options.AddArgument("--headless");
// GPU加速可能会导致Chrome出现黑屏及CPU占用率过高
options.AddArgument("--nogpu");
// 设置chrome启动时size大小
options.AddArgument("--window-size=10,10");
using (var driver = new ChromeDriver(options))
{
try
{
driver.Manage().Window.Minimize();
driver.Navigate().GoToUrl(url);
// 等待页面动态加载完成
Thread.Sleep(5000);
// 返回页面源码
return driver.PageSource;
}
catch (NoSuchElementException)
{
Console.WriteLine("找不到该元素");
return string.Empty;
}
}
}
解析 HTML 文档
这里以B站为例,爬取B站UP主主页上的视频信息,如视频的标题、链接、封面。
先定义一个类来保存信息:
class VideoInfo
{
public string Title { get; set; }
public string Href { get; set; }
public string ImgUrl { get; set; }
}
定义解析函数,返回视频信息列表:
private static List<VideoInfo> GetVideoInfos(string url)
{
List<VideoInfo> videoInfos = new List<VideoInfo>();
// 加载文档
var html = GetHtml(url);
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(html);
// 解析文档,先定位到视频列表标签
var xpath = "/html/body/div[2]/div[4]/div/div/div[1]/div[2]/div/div";
var htmlNodes = htmlDoc.DocumentNode.SelectNodes(xpath);
// 循环解析它的子节点视频信息
foreach (var node in htmlNodes)
{
var titleNode = node.SelectSingleNode("a[2]");
var imgNode = node.SelectSingleNode("a[1]/div[1]/picture/source[1]");
var title = titleNode.InnerText;
var href = titleNode.Attributes["href"].Value.Trim('/');
var imgUrl = imgNode.Attributes["srcset"].Value.Split('@')[0].Trim('/');
videoInfos.Add(new VideoInfo
{
Title = title,
Href = href,
ImgUrl = imgUrl
});
}
return videoInfos;
}
视频列表标签的 XPath 路径是通过浏览器调试工具,在指定标签上右键 复制完整的XPath 得到:

分析代码中的 node 节点时,html文本格式可能很乱,可以通过在线 HTML 代码格式化 工具格式后再进行分析。
测试
以B站UP主 星瞳_Official 为例,爬取视频信息:
static void Main(string[] args)
{
var url = @"https://space.bilibili.com/401315430";
var videoInfos = GetVideoInfos(url);
foreach (var videoInfo in videoInfos)
{
Console.WriteLine(videoInfo.Title);
Console.WriteLine(videoInfo.Href);
Console.WriteLine(videoInfo.ImgUrl);
Console.WriteLine();
}
Console.ReadKey();
}
结果如下:
等一下,好妹妹
www.bilibili.com/video/BV1uyxLeJEM9
i0.hdslb.com/bfs/archive/46a15065d1b6722a04696ffaaa2235287ceaa452.jpg
一口一个?你的超甜辣椒
www.bilibili.com/video/BV1AQsDeiEn1
i0.hdslb.com/bfs/archive/d93d47d67323ee284483e963ffed34fb9884cf61.jpg
这里只是演示爬取动态页面的方法,如果想获取B站UP主的视频信息,建议直接使用 API 请求数据。
参考文章
C#爬取动态网页上的信息:B站主页的更多相关文章
- R语言爬取动态网页之环境准备
在R实现pm2.5地图数据展示文章中,使用rvest包实现了静态页面的数据抓取,然而rvest只能抓取静态网页,而诸如ajax异步加载的动态网页结构无能为力.在R语言中,爬取这类网页可以使用RSele ...
- 记录几个爬取动态网页时的问题(下拉框,旧的元素无法获取,获取的源代码和f12看到的不一致,爬取延迟)
更新.....这个动态网页其实直接抓取ajax请求就可以了,很简单,我之前想复杂了,虽然也实现了,但是效率极低,不过没关系,就当作是对Selenium的一次学习吧 1.最近在爬取一个动态网页,其中为了 ...
- python爬取动态网页数据,详解
原理:动态网页,即用js代码实现动态加载数据,就是可以根据用户的行为,自动访问服务器请求数据,重点就是:请求数据,那么怎么用python获取这个数据了? 浏览器请求数据方式:浏览器向服务器的api(例 ...
- 爬虫(三)通过Selenium + Headless Chrome爬取动态网页
一.Selenium Selenium是一个用于Web应用程序测试的工具,它可以在各种浏览器中运行,包括Chrome,Safari,Firefox 等主流界面式浏览器. 我们可以直接用pip inst ...
- 利用selenium并使用gevent爬取动态网页数据
首先要下载相应的库 gevent协程库:pip install gevent selenium模拟浏览器访问库:pip install selenium selenium库相应驱动配置 https: ...
- 爬取动态网页:Selenium
参考:http://blog.csdn.net/wgyscsf/article/details/53454910 概述 在爬虫过程中,一般情况下都是直接解析html源码进行分析解析即可.但是,有一种情 ...
- python爬取动态网页2,从JavaScript文件读取内容
import requests import json head = {"user-agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) ...
- nodejs爬虫笔记(三)---爬取YouTube网站上的视频信息
思路:通过笔记(二)中代理的设置,已经可以对YouTube的信息进行爬取了,这几天想着爬取网站下的视频信息.通过分析YouTube,发现可以从订阅号入手,先选择几个订阅号,然后爬取订阅号里面的视频分类 ...
- Python+Selenium爬取动态加载页面(2)
注: 上一篇<Python+Selenium爬取动态加载页面(1)>讲了基本地如何获取动态页面的数据,这里再讲一个稍微复杂一点的数据获取全国水雨情网.数据的获取过程跟人手动获取过程类似,所 ...
- Python+Selenium爬取动态加载页面(1)
注: 最近有一小任务,需要收集水质和水雨信息,找了两个网站:国家地表水水质自动监测实时数据发布系统和全国水雨情网.由于这两个网站的数据都是动态加载出来的,所以我用了Selenium来完成我的数据获取. ...
随机推荐
- vue小知识:多层数据双向相应之向上派发和向下派发($dispatch和$broadcast)
注意:这两个实例已经在vue3中弃用啦!!!(所以不详细说了,封装知道怎么用就行了,作为了解) 都是在vue实例配置(main.js) 向上派发:$dispatch 注意,在相应后代组件中使用 thi ...
- midjourney 生成相似类型图片
生成类似形象 midjourney 核心就是一次运行3次图片,多尝试 上传此图片到discord里的mj -> 复制图片的link -> 使用describe拆词 也可以自己手动拆词,人工 ...
- 【Vue】HutoolExcel导出
最近写Excel导出功能,发现需求有点复杂,这里整理一下思路和解决方案 一.需求背景: 老系统改造,功能和代码是现成的,预览了一下内容: 第一个是有特定样式,比如首行标题,以及红色的列名称 第二个,导 ...
- 国产最好用的操作系统——deepin,为什么不适合生产环境
前几天看了罗永浩的视频,他推荐了一本Intel创始人的书,看了这本书后想到书中大谈Intel和Microsoft的合作才创建下了今天的PC世界.看到这我就有些不爽了,现在美国各种控制和制裁我们的芯片, ...
- 后端开发学习敏捷需求-->产品价值的定位
产品价值的定位 为什么要写这一系列文章 2023年网上报名学习了,敏捷软件需求的培训课程 ,一直都没有进行回顾,回顾学习,总结 业务分析的能力偏弱,学习和了解关于业务需求相关的方法和理论 每一年都有一 ...
- 023.Ubuntu常见个性化配置
root登录设置 ubuntu默认关闭了root账户,可根据实际情况开启或关闭root登录. ubuntu@localhost:~$ sudo apt install openssh-server u ...
- 【牛客刷题】HJ6 质数因子
题目链接 这道题本身更多的是考察如何计算一个数的质数因子,更像是一道数学题,用到了循环的方法: package main import ( "fmt" "math&quo ...
- 微服务全链路跟踪:springcloud集成jaeger
微服务全链路跟踪:grpc集成zipkin 微服务全链路跟踪:grpc集成jaeger 微服务全链路跟踪:springcloud集成jaeger 微服务全链路跟踪:jaeger集成istio,并兼容u ...
- 瑞芯微 | 如何固定以太口地址为指定ip?ifplugd妙用
rxw的RK3568的evb1公板,有2个以太口, 默认UI界面只能配置eth0,无法配置eth1, 实际应用中,有时需要一旦有网线插入,就需要该地址设置为指定IP地址. 本文介绍2个最简单的方法实现 ...
- JavaScript设计模式样例十九 —— 职责链模式
职责链模式(Chain of Responsibility Pattern) 定义:为请求创建了一个接收者对象的链. 目的:避免请求发送者与接收者耦合在一起,让多个对象都有可能接收请求,将这些对象连接 ...