最近需要学习一些C#爬虫技术,在网上看到了有大佬使用HtmlAgilityPack和ScrapySharp爬取新闻https://www.cnblogs.com/lmei/p/3662374.html,
然后我就找了一个自己需要的网站http://www.ahmhxc.com/,进行爬取多个网页新闻的标题,摘要,内容的测试。
首先第一步,在NuGet里面安装HtmlAgilityPack和ScrapySharp,至于过程我就不详细的说了。反正就是点点点。
先写一个下载类,这个下载类主要是实现的就是传入一个uri,之后就从该uri上下载html文件,再从uri中截取下我们需要的文件;
using System;
using System.Text;
using ScrapySharp.Extensions;
using ScrapySharp.Network;
using HtmlAgilityPack;
using System.Collections.Generic;
namespace SolvePageFaceCode
{
class Download
{
/// <summary>
/// 下载标题和摘要
/// </summary>
/// <param name="uri"></param>
/// <returns></returns>
public string DownloadFile(Uri uri)
{
ScrapingBrowser browser1 = new ScrapingBrowser { Encoding =Encoding.GetEncoding ("gb2312")};
string html1 = browser1.DownloadString(uri);
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html1);
HtmlNode htmlNode= doc.DocumentNode;
IEnumerable <HtmlNode> title = htmlNode.CssSelect("div.title") ;//html中的div class=title标题
IEnumerable<HtmlNode> des = htmlNode.CssSelect("div.des");//html中的div class=des摘要
var test = htmlNode.CssSelect("p");//选择所有带有<p></p>中间数据,使用var只是说明还有这种用法
string returnStr = "";
foreach (var node in title)//IEumerable需要这样遍历
{
returnStr += node.InnerText;
}
returnStr += "\n";
foreach (var node in des)
{
returnStr += node.InnerText;
}
returnStr += "\n";
foreach (var node in test)
{
returnStr += node.FirstChild.InnerText;//所有对HtmlNode的操作都需要在这里进行
}
return returnStr;
}
}
}
关于C#中CssSelect的一些使用:
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标签。
4、其他:
var divs = html.CssSelect(“div”); //all div elements
var nodes = html.CssSelect(“div.content”); //all div elements with css class ‘content’
var nodes = html.CssSelect(“div.widget.monthlist”); //all div elements with the both css class
var nodes = html.CssSelect("#postPaging"); //all HTML elements with the id postPaging
var nodes = html.CssSelect(“div#postPaging.testClass”); // all HTML elements with the id postPaging and css class testClass
var nodes = html.CssSelect(“div.content > p.para”); //p elements who are direct children of div elements with css class ‘content’
var nodes = html.CssSelect(“input[type=text].login”); // textbox with css class login
We can also select ancestors of elements:
var nodes = html.CssSelect(“p.para”).CssSelectAncestors(“div.content > div.widget”);
接下来点开这个网站中的几条工作报。
我们可以发现,网址是有规律可循的;
如下:
http://www.ahmhxc.com/gongzuobaogao/15217.html
这段网址可以分为三段。
第一段为http://www.ahmhxc.com/
第二段为gongzuobaogao/
第三段为15217.html
因此开始构建我们的uri
private static string GetLink(int paperNum,int pageNum)
{
string Link = "http://www.ahmhxc.com/";
string[] paperNames = { "tongjigongbao/", "gongzuobaogao/" };//0统计公报,1工作报告
try
{
Link += paperNames[paperNum];
Link += pageNum.ToString() + ".html";
}
catch
{
return null;
}
return Link;
}
最后粘贴上所有的Program中的C#代码
using System;
namespace SolvePageFaceCode
{
class Program
{
static void Main(string[] args)
{
string link = "";
int times = 0;
while (times < 2)
{
for (int i = 10000; i < 10020; i++)//这里次数可以增加,因为数据太多,所以就弄得比较少
{
try
{
link = GetLink(times, i);
Uri uri = new Uri(link);
Download download = new Download();
string one = download.DownloadFile(uri);
//one = StrExtract(one,times);
Console.WriteLine(one);
}
catch
{
continue;
}
}
times++;
}
Console.ReadKey();
}
/// <summary>
/// 进行链接的编辑
/// </summary>
/// <param name="paperNum"></param>报纸序号
/// <param name="pageNum"></param>页码
/// <returns></returns>
private static string GetLink(int paperNum,int pageNum)
{
string Link = "http://www.ahmhxc.com/";
string[] paperNames = { "tongjigongbao/", "gongzuobaogao/" };//0统计公报,1工作报告
try
{
Link += paperNames[paperNum];
Link += pageNum.ToString() + ".html";
}
catch
{
return null;
}
return Link;
}
}
输出如下: