.net爬虫使用HtmlAgilityPack爬取网络数据

2023-11-07 15:40

本文主要是介绍.net爬虫使用HtmlAgilityPack爬取网络数据,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 一、HtmlAgilityPack是什么?
  • 二、使用步骤
    • 1.引入库
    • 2.HtmlAgilityPack语法
  • 总结




前言

最近在研究python爬虫,发现没有网上传的那么神奇,其实也只是python中爬虫类库比较丰富,其中的的request、json、selenium这些爬虫类库,.net也是有的,并且实现也不是很困难(本人还是很倾向C#/net的毕竟开发启蒙语言是这个)所以本文简单介绍下.net爬虫。这里在开始之前先看下我用爬虫爬取电影数据后做的网站

爬取数据后的演示地址:北辰

使用工具及框架

开发工具:VS2019

框架:简单三层:Model,BLL,DAL



一、HtmlAgilityPack是什么?

HtmlAgilityPack是.net下开源的免费类库,他的优点是可以将html文档解析成可以用xpath语法(即为XML路径语言,它是一种用来确定XML(标准通用标记语言的子集)文档中某部分位置的语言。XPath基于XML的树状结构,有不同类型的节点,包括元素节点,属性节点和文本节点,提供在数据结构树中找寻节点的能力),简单点说就是可以像操作xml文档那样操作html。




二、使用步骤



1.引入库

首先在VS2019中安装HtmlAgilityPack

工具--》NuGet--》下载HtmlAgilityPack



2.HtmlAgilityPack语法 

1、获取网页title:doc.DocumentNode.SelectSingleNode("//title").InnerText;  解释:XPath中“//title”表示所有title节点。SelectSingleNode用于获取满足条件的唯一的节点。
2、获取所有的超链接:doc.DocumentNode.Descendants("a")
3、获取name为kw的input,也就是相当于getElementsByName():            

var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name='kw']");
解释:"//input[@name='kw']"也是XPath的语法,表示:name属性等于kw的input标签。
//li/h3/a[@href]:所有li下面的h3包含a超级链接有href属性才符合。有的a可能是支持的js事件
//div[starts-with(@class,'content_single')]:所有符合条件的div,并且它的class是由字符串content_single 开头的
注意路径里"//"表示从根节点开始查找,两个斜杠‘//’表示查找所有childnodes;一个斜杠'/'表示只查找第一层的childnodes(即不查找grandchild);点斜杠"./"表示从当前结点而不是根结点开始查找

3.开始代码

//因为要用到HttpRequest请求页面,所以这里设置了请求的头部信息useragents,可以让服务器以为这是浏览器发起的请求。
private readonly string[] usersagents = new string[] {"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1","MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1","JUC (Linux; U; 2.3.7; zh-cn; MB200; 320*480) UCWEB7.9.3.103/139/999","Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0a1) Gecko/20110623 Firefox/7.0a1 Fennec/7.0a1","Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10","Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13","Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/1A542a Safari/419.3","Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_0 like Mac OS X; en-us) AppleWebKit/532.9 (KHTML, like Gecko) Version/4.0.5 Mobile/8A293 Safari/6531.22.7","Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B334b Safari/531.21.10","Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+","Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0","Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124","Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2228.0 Safari/537.36","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2227.1 Safari/537.36","Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10","Mozilla/5.0 (Windows NT 5.1; U; en; rv:1.8.1) Gecko/20061208 Firefox/2.0.0 Opera 9.50","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2 (KHTML, like Gecko) Version/5.1.7 Safari/534.57.2","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER) ","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.122 UBrowser/4.0.3214.0 Safari/537.36","Mozilla/5.0 (Linux; U; Android 2.2.1; zh-cn; HTC_Wildfire_A3333 Build/FRG83D) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1","Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+","Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)","Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999","Openwave/ UCWEB7.0.2.37/28/999","NOKIA5700/ UCWEB7.0.2.37/28/999","UCWEB7.0.2.37/28/999","Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0","Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13","Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10","Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",};private void btn_TestConnect_Click(object sender, EventArgs e){//这里使用委托的方式防止阻塞UI线程Action<int> downImg = DownAllPageImg;downImg.BeginInvoke(int.Parse(numStartPage.Value.ToString()), null, null);}
public void DownAllPageImg(int StartPage){int i = StartPage;int continueNum = 1;//我这里使用的是WinForm模式开发的,这句话意思是可以跨线程访问,即当前线程可以访问UI线程。CheckForIllegalCrossThreadCalls = false;while (true){//设置从第几页开始爬取txtBeginPage.Text = i.ToString();i++;try{HttpWebRequest request = null;HttpWebResponse response = null;Stream stream = null;StreamReader reader = null;var url = string.Empty;string result = string.Empty;Encoding encoding = Encoding.Default;if (i == 1){url = "http://vipshipin.vip/";}else{url = "http://vipshipin.vip/index/" + i;}//请求地址request = (HttpWebRequest)WebRequest.Create(url);//随机使用一个useragentsvar randomNumber = random.Next(0, usersagents.Length);request.UserAgent = usersagents[randomNumber];request.Timeout = 30000;request.ServicePoint.Expect100Continue = false;request.KeepAlive = false;response = (HttpWebResponse)request.GetResponse();if (response.StatusCode == HttpStatusCode.OK){using (stream = response.GetResponseStream()){reader = new StreamReader(stream);result = reader.ReadToEnd();stream.Close();//这里就使用HtmlAgilityPack来解析request请求返回的HTMLHtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();doc.LoadHtml(result);//这里的意思是获取所有div的class='col-sm-2 col-xs-6 fix'的节点var node = doc.DocumentNode.SelectNodes("//div[@class='col-sm-2 col-xs-6 fix']");if (node == null){continueNum++;if (continueNum > 3){break;}continue;}//查询node节点div所有子节点var titleA0 = node.Select(x => x.ChildNodes);//集合中的每一个都返回第一个符合条件的 此处返回所有a标签的属性var ttc = titleA0.Select(x => x.First(z => z.Name == "a"));List<movies_tb> moviesList = new List<movies_tb>();List<string> imgList = new List<string>();foreach (var item in ttc){var title = item.Attributes.Where(x => x.Name == "title").FirstOrDefault().Value;var oldidstr = item.Attributes.Where(x => x.Name == "href").FirstOrDefault().Value;//两段字符之间的id号例如:https://www.vipshipin.vip/156466.html  获取156466var oldidint = int.Parse(oldidstr.Substring(oldidstr.LastIndexOf('/') + 1, oldidstr.LastIndexOf('.') - oldidstr.LastIndexOf('/') - 1));//简单三层判断id是否存在,若存在则跳过if (bllMovie.ExistsOldId(oldidint)){continue;}else{var imgsrc = "http:" + item.SelectNodes("img").FirstOrDefault().Attributes.Where(x => x.Name == "data-original").FirstOrDefault().Value;//这里添加图片var by02= ImgPath(imgsrc);moviesList.Add(new movies_tb { title = title, oldid = oldidint, imgsrc = imgsrc,by_02= by02 });imgList.Add(imgsrc);FileStream fs = new FileStream(noimglog, FileMode.Append);StreamWriter sw = new StreamWriter(fs);sw.WriteLine("page"+i);sw.Close();}}List<CommandInfo> cmdList = Common.GetAllSQLWithParamers(moviesList);SpiderFormMovieSite.BLL.movies_tb moviesBll = new SpiderFormMovieSite.BLL.movies_tb();//开启线程工程,创建线程,第一个是执行sql插入从中,第二个是下载所有图片,下载图片的方法也是用HttpRequest请求下载地址然后保存图片Task.WaitAll(new Task[] {Task.Factory.StartNew(() => moviesBll.ExecuteSqlTran(cmdList)),Task.Factory.StartNew(() => DownLoadAllImg(imgList))});//Thread.Sleep(5000);reader.Close();stream.Close();response.Close();}response.Close();}}catch (Exception){throw;}}}

 上面代码中的下面几句,就是利用HtmlAgilityPack将html文档实例化成htmlDom

//这里就使用HtmlAgilityPack来解析request请求返回的HTML
HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(result);
//这里的意思是获取所有div的class='col-sm-2 col-xs-6 fix'的节点
var node = doc.DocumentNode.SelectNodes("//div[@class='col-sm-2 col-xs-6 fix']");

var node = doc.DocumentNode.SelectNodes("//div[@class='col-sm-2 col-xs-6 fix']");

这句话的意思就是从html根目录下找到所有div 中class='col-sm-2 col-xs-6 fix' 的节点即为下面的图片:

这样页面中所有的链接和图片资源都可以找到了

//获取标题

var title = item.Attributes.Where(x => x.Name == "title").FirstOrDefault().Value;

然后将获取的数据进行提取,将所需的电影名称和图片保存到本地:

//开启线程工程,创建线程,第一个是执行sql插入从中,第二个是下载所有图片,下载图片的方法也是用HttpRequest请求下载地址然后保存图片Task.WaitAll(new Task[] {Task.Factory.StartNew(() => moviesBll.ExecuteSqlTran(cmdList)),Task.Factory.StartNew(() => DownLoadAllImg(imgList))});

 这里创建线程一个去执行将所有字段插入数据库,第二个执行DownLoadAllImg就是下载当前页面所有的图片保存到本地的操作,这个方法也是先用HttpRequest将图片地址请求到,然后用文件流将文件保存到本地。





总结

1.利用HttpRequest先请求网站,获取返回后的html

2.利用HtmlAgilityPack将html变成和操作xpath语法一样的操作,基本操作为:

        2.1、获取网页title:doc.DocumentNode.SelectSingleNode("//title").InnerText;  解释:XPath中“//title”表示所有title节点。SelectSingleNode用于获取满足条件的唯一的节点。

        2.2、获取所有的超链接:doc.DocumentNode.Descendants("a")

        2.3、获取name为kw的input,也就是相当于getElementsByName():             var kwBox = doc.DocumentNode.SelectSingleNode("//input[@name='kw']");

解释:"//input[@name='kw']"也是XPath的语法,表示:name属性等于kw的input标签。

//li/h3/a[@href]:所有li下面的h3包含a超级链接有href属性才符合。有的a可能是支持的js事件

//div[starts-with(@class,'content_single')]:所有符合条件的div,并且它的class是由字符串content_single 开头的

/Articles/Article[1]:选取属于Articles子元素的第一个Article元素。 

 /Articles/Article[last()]:选取属于Articles子元素的最后一个Article元素。 

 /Articles/Article[last()-1]:选取属于Articles子元素的倒数第二个Article元素。 

 /Articles/Article[position()<3]:选取最前面的两个属于 bookstore 元素的子元素的Article元素。 

 //title[@lang]:选取所有拥有名为lang的属性的title元素。 

 //CreateAt[@type='zh-cn']:选取所有CreateAt元素,且这些元素拥有值为zh-cn的type属性。 

 /Articles/Article[Order>2]:选取Articles元素的所有Article元素,且其中的Order元素的值须大于2。 

 /Articles/Article[Order<3]/Title:选取Articles元素中的Article元素的所有Title元素,且其中的Order元素的值须小于3。

3.插入数据,保存图片。

这篇关于.net爬虫使用HtmlAgilityPack爬取网络数据的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/364619

相关文章

python使用库爬取m3u8文件的示例

《python使用库爬取m3u8文件的示例》本文主要介绍了python使用库爬取m3u8文件的示例,可以使用requests、m3u8、ffmpeg等库,实现获取、解析、下载视频片段并合并等步骤,具有... 目录一、准备工作二、获取m3u8文件内容三、解析m3u8文件四、下载视频片段五、合并视频片段六、错误

javax.net.ssl.SSLHandshakeException:异常原因及解决方案

《javax.net.ssl.SSLHandshakeException:异常原因及解决方案》javax.net.ssl.SSLHandshakeException是一个SSL握手异常,通常在建立SS... 目录报错原因在程序中绕过服务器的安全验证注意点最后多说一句报错原因一般出现这种问题是因为目标服务器

CSS place-items: center解析与用法详解

《CSSplace-items:center解析与用法详解》place-items:center;是一个强大的CSS简写属性,用于同时控制网格(Grid)和弹性盒(Flexbox)... place-items: center; 是一个强大的 css 简写属性,用于同时控制 网格(Grid) 和 弹性盒(F

CSS实现元素撑满剩余空间的五种方法

《CSS实现元素撑满剩余空间的五种方法》在日常开发中,我们经常需要让某个元素占据容器的剩余空间,本文将介绍5种不同的方法来实现这个需求,并分析各种方法的优缺点,感兴趣的朋友一起看看吧... css实现元素撑满剩余空间的5种方法 在日常开发中,我们经常需要让某个元素占据容器的剩余空间。这是一个常见的布局需求

CSS Anchor Positioning重新定义锚点定位的时代来临(最新推荐)

《CSSAnchorPositioning重新定义锚点定位的时代来临(最新推荐)》CSSAnchorPositioning是一项仍在草案中的新特性,由Chrome125开始提供原生支持需... 目录 css Anchor Positioning:重新定义「锚定定位」的时代来了! 什么是 Anchor Pos

CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比

《CSS中的Static、Relative、Absolute、Fixed、Sticky的应用与详细对比》CSS中的position属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布... css 中的 position 属性用于控制元素的定位方式,不同的定位方式会影响元素在页面中的布局和层叠关

HTML5 getUserMedia API网页录音实现指南示例小结

《HTML5getUserMediaAPI网页录音实现指南示例小结》本教程将指导你如何利用这一API,结合WebAudioAPI,实现网页录音功能,从获取音频流到处理和保存录音,整个过程将逐步... 目录1. html5 getUserMedia API简介1.1 API概念与历史1.2 功能与优势1.3

gitlab安装及邮箱配置和常用使用方式

《gitlab安装及邮箱配置和常用使用方式》:本文主要介绍gitlab安装及邮箱配置和常用使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1.安装GitLab2.配置GitLab邮件服务3.GitLab的账号注册邮箱验证及其分组4.gitlab分支和标签的

SpringBoot3应用中集成和使用Spring Retry的实践记录

《SpringBoot3应用中集成和使用SpringRetry的实践记录》SpringRetry为SpringBoot3提供重试机制,支持注解和编程式两种方式,可配置重试策略与监听器,适用于临时性故... 目录1. 简介2. 环境准备3. 使用方式3.1 注解方式 基础使用自定义重试策略失败恢复机制注意事项

nginx启动命令和默认配置文件的使用

《nginx启动命令和默认配置文件的使用》:本文主要介绍nginx启动命令和默认配置文件的使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录常见命令nginx.conf配置文件location匹配规则图片服务器总结常见命令# 默认配置文件启动./nginx