c#抓取网页数据( 为什么要了解百度新闻中热点要闻版块提高站点百度排名)
优采云 发布时间: 2022-04-06 19:10c#抓取网页数据(
为什么要了解百度新闻中热点要闻版块提高站点百度排名)
图1
如图1所示,在我们的工作过程中,无论是平台网站还是公司官网,总会有新闻展示。比如某天产品经理告诉我们,推广员想抢百度新闻的热点新闻版块,以提高网站的百度排名。要抢百度热点新闻版,首先要了解站点请求头(Request headers)信息。
为什么要了解请求标头(Request headers)信息?
原因在于,我们可以根据请求头信息中的某部分消息信息,而不是通过人工爬虫程序规避站点屏蔽,来伪装这是一个正常的HTTP请求,成功获取响应数据(Response data)。
如何查看百度新闻URL的请求头信息?
图 2
如图2,我们可以打开谷歌浏览器或者其他浏览器开发工具(按F12)查看站点的请求头消息信息。从图中可以看出百度新闻站点可以接受文本/html 等数据类型;语言为中文;浏览器版本为 Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 ( KHTML,如 Gecko ) Chrome/66.0.3359.181 Safari/537.36 等消息信息,我们在发起 HTTP 时直接携带消息信息request 过去,当然不是每一个包信息参数都必须携带过去,一部分可以被成功请求。
那么什么是响应数据?
图 3
如图3所示,响应数据(Response data)可以从谷歌浏览器或者其他浏览器开发工具中查看(按F12)查看,响应可以是数据或者DOM树数据,方便我们的后续分析数据。
当然,你可以学习任何开发语言来开发爬虫程序:C#、NodeJs、python、java、C++。
不过这里主要讲C#爬虫程序的开发。微软为我们提供了HTTP请求的两个HttpWebRequest和HttpWebResponse对象,方便我们发送请求获取数据。下面显示了 C# HTTP 请求代码:
private string RequestAction(RequestOptions options)
{
string result = string.Empty;
IWebProxy proxy = GetProxy();
var request = (HttpWebRequest)WebRequest.Create(options.Uri);
request.Accept = options编程客栈.Accept;
//在使用curl做POST的时候, 当要POST的数据大于1024字节的时候, curl并不会直接就发起POST请求, 而是会分为俩步,
//发送一个请求, 包含一个Expect: 100 -continue, 询问Server使用愿意接受数据
//接收到Server返回的100 - continue应答以后, 才把数据POST给Server
//并不是所有的Server都会正确应答100 -continue, 比如lighttpd, 就会返回417 “Expectation Failed”, 则会造成逻辑出错.
request.ServicePoint.Expect100Continue = false;
request.ServicePoint.UseNagleAlgorithm = false;//禁止Nagle算法加快载入速度
if (!string.IsNullOrEmpty(options.XHRParams)) { request.AllowWriteStreamBuffering = true; } else { request.AllowWriteStreamBuffering = false; }; //禁止缓冲加快载入速度
request.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");//定义gzip压缩页面支持
request.ContentType = options.ContentType;//定义文档类型及编码
request.AllowAutoRedirect = options.AllowAutoRedirect;//禁止自动跳转
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebhttp://www.cppcns.comKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36";//设置User-Agent,伪装成Google Chrome浏览器
request.Timeout = options.Timeout;//定义请求超时时间为5秒
request.KeepAlive = options.KeepAlive;//启用长连接
if (!string.IsNullOrEmpty(options.Referer)) request.Referer = options.Referer;//返回上一级历史链接
request.Method = options.Method;//定义请求方式为GET
if (proxy != null) request.Proxy = proxy;//设置代理服务器IP,伪装请求地址
if (!string.IsNullOrEmpty(options.RequestCookies)) request.Headers[HttpRequestHeader.Cookie] = options.RequestCookies;
request.ServicePoint.ConnectionLimit = options.ConnectionLimit;//定义最大连接数
if (options.WebHeader != null && options.WebHeader.Count > 0) request.Headers.Add(options.WebHeader);//添加头部信息
if (!string.IsNullOrEmpty(options.XHRParams))//如果是POST请求,加入POST数据
{
byte[] buffer = Encoding.UTF8.GetBytes(options.XHRParams);
if (buffer != null)
{
request.ContentLength = buffer.Length;
request.GetRequestStream().Write(buffer, 0, buffer.Length);
}
}
using (var response = (HttpWebResponse)request.GetResponse())
{
////获取请求响应
//foreach (Cookie cookie in response.Cookies)
// options.CookiesContainer.Add(cookie);//将Cookie加入容器,保存登录状态
if (response.ContentEncoding.ToLower().Contains("gzip"))//解压
{
using (GZipStream stream = new GZipStream(response.GetResponseStream(), CompressionMode.Decompress))
{
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
}
}
else if (response.ContentEncoding.ToLower().Contains("deflate"))//解压
{
using (DeflateStream stream = new DeflateStream(response.GetResponseStream(), CompressionMode.Decompress))
{
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadToEnd();
}
}
}
else
{
using (Stream stream = response.GetResponseStream())//原始
{
using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
{
result = reader.ReadT编程客栈oEnd();
}
}
}
}
request.Abort();
return result;
}
还有一个我传入的自定义对象。当然,传入或传出对象由你根据实际业务需求定义:
public class RequestOptions
{
///
/// 请求方式,GET或POST
///
public string Method { get; set; }
///
/// URL
///
public Uri Uri { get; set; }
///
/// 上一级历史记录链接
///
public string Referer { get; set; }
///
/// 超时时间(毫秒)
///
public int Timeout = 15000;
///
/// 启用长连接
///
public bool KeepAlive = true;
///
/// 禁止自动跳转
///
public bool AllowAutoRedirect = false;
/// &http://www.cppcns.comlt;summary>
/// 定义最大连接数
///
public int ConnectionLimit = int.MaxValue;
//编程客栈/
/// 请求次数
///
public int RequestNum = 3;
///
/// 可通过文件上传提交的文件类型
///
public string Accept = "*/*";
///
/// 内容类型
///
public string ContentType = "application/x-www-form-urlencoded";
///
/// 实例化头部信息
///
private WebHeaderCollection header = new WebHeaderCollection();
///
/// 头部信息
///
public WebHeaderCollection WebHeader
{
get { return header; }
set { header = value; }
}
///
/// 定义请求Cookie字符串
///
public string RequestCookies { get; set; }
///
/// 异步参数数据
///
public string XHRParams { get; set; }
}
根据显示的代码,我们可以发现 HttpWebRequest 对象封装了很多 Request headers 消息参数。我们可以根据网站的Request headers信息在微软提供的HttpWebRequest对象中设置(见代码消息参数注释,都写了相关参数说明,如果理解有误,请告知,谢谢你),然后发送请求获取响应数据来解析数据。
还补充一点,爬虫程序最好使用代理IP来使用代理IP,这样可以降低被屏蔽的概率,提高爬取效率。但是,代理IP也分为质量等级。对于某些 HTTPS 站点,可能需要质量级别更高的代理 IP 才能穿透。我不会在这里跑题。我会写一篇关于代理IP质量等级的文章文章详情说说我的看法。
C#代码如何使用代理IP?
Microsoft NET 框架还为我们提供了一个使用代理 IP 的 System.Net.WebProxy 对象。使用代码如下:
private System.Net.WebProxy GetProxy()
{
System.Net.WebProxy webProxy = null;
try
{
// 代理链接地址加端口
string proxyHost = "192.168.1.1";
string proxyPort = "9030";
// 代理身份验证的帐号跟密码
//string proxyUser = "xxx";
//string proxyPass = "xxx";
// 设置代理服务器
webProxy = new System.Net.WebProxy();
// 设置代理地址加端口
webProxy.Address = new Uri(string.Format("{0}:{1}", proxyHost, proxyPort));
// 如果只是设置代理IP加端口,例如192.168.1.1:80,这里直接注释该段代码,则不需要设置提交给代理服务器进行身份验证的帐号跟密码。
//webProxy.Credentials = new System.Net.NetworkCredential(proxyUser, proxyPass);
}
catch (Exception ex)
{
Console.WriteLine("获取代理信息异常", DateTime.Now.ToString(), ex.Message);
}
return webProxy;
}
关于System.Net.WebProxy对象的参数说明,我也在代码中进行了说明。
如果获取的Response数据是json、xml等格式的数据,这里就不详细描述这种数据解析方式了,请自行百度。这里的主要主题是 DOM 树 HTML 数据的解析。对于这类数据,有的人会使用正则表达式来解析,有的人会使用组件。当然,只要你能得到你想要的数据,你就可以按照你想要的方式解析它。这里的重点是我经常使用解析组件HtmlAgilityPack,参考DLL是(使用HtmlAgilityPack)。解析代码如下:
HtmlDocument htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(simpleCrawlResult.Contents);
HtmlNodeCollection liNodes = htmlDoc.DocumentNode.SelectSingleNode("//div[@id='pane-news']").SelectSingleNode("div[1]/ul[1]").SelectNodes("li");
if (liNodes != null && liNodes.Count > 0)
{
for (int i = 0; i < liNodes.Count; i++)
{
string title = liNodes[i].SelectSingleNode("strong[1]/a[1]").InnerText.Trim();
string href = liNodes[i].SelectSingleNode("strong[1]/a[1]").GetAttributeValue("href", "").Trim();
Console.WriteLine("新闻标题:" + title + ",链接:" + href);
}
}
下面主要展示爬取结果。
图 4
如图4,抓包效果,一个简单的爬虫程序就这样完成了。
至此,这篇关于c#实现爬虫程序的文章文章就介绍到这里了。希望对您的学习有所帮助,也希望您多多支持。
本文标题:c#实现爬虫程序