利用Http状态码检查网页内容是否更新
2009-12-20 12:52
337 查看
在做网页抓取爬虫类的工具时,经常要对页面进行监控和解析,其中监控就是检查页面内容是否发生了更新。判断网页是否发生变化最直接的方法是设置页面的某一处为监控区域,每次都抓取该部分区域的内容,然后与本地保存的或最近一次抓取内容比较,如果有差异就表明网页发生了变化,才可以进行解析。这种方法比较稳妥,几乎可达到万无一失的效果。但是,这种方式在每次扫描时都要下载页面内容,并且要去截取监控区域的内容,最后还要进行字符串比较,整个过程比较耗时。其实在众多网页中,有一部分网站的网页内容是静态页面,如图片,html,js等,这些静态页面往往可能是服务器早已准备好的,用户访问时仅仅是下载而已。那么针对这种静态页面,就可以仅仅通过状态码来判断,内容是否发生了变化。
这个状态码就是304(Not Modified),对于这个代码的解释是"如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码"。很明显通过这个解释,我们就明白了其实现的机理。我们要做的事情,仅仅是在发送请求时将上次访问的时间添加到header中,然后根据服务器返回的状态码进行判断。通常,在网页发生变化时,服务器会返回状态码200,而未发生变化则返回304。
dotnet在网络传输这块已经提供了完善的API,接下来请看具体的实现方式。在这个例子中,通过访问国家统计局的banner页面(http://www.stats.gov.cn/top.html)来演示,分别检查3天前和3个月前该页面是否发生了变化。
static void Main(string[] args)
{
string url = "http://www.stats.gov.cn/top.html";
// 检查3天前网页是否发生了变化
DateTime modifiedSince = DateTime.Now.AddDays(-3);
// 输出false
Console.WriteLine(PageHasChanged(url, modifiedSince));
// 检查3个月前是否发生了变化
modifiedSince = DateTime.Now.AddMonths(-3);
// 输出true
Console.WriteLine(PageHasChanged(url, modifiedSince));
}
private static bool PageHasChanged(string url, DateTime modifiedSince)
{
bool changed = false;
// 设置请求信息
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
// 最关键的一项设置 将请求的IfModifiedSince设置为指定的时间
request.IfModifiedSince = modifiedSince;
HttpWebResponse response = null;
try
{
response = request.GetResponse() as HttpWebResponse;
// 根据返回的状态码判断内容是否发生了变化
// 200表示页面发生了变化
if (response.StatusCode == HttpStatusCode.OK)
{
changed = true;
}
else if (response.StatusCode == HttpStatusCode.NotModified)
{
changed = false;
}
response.Close();
}
catch (WebException ex)
{
// 对于没有发生变化的页面 通常会通过抛出异常的方式提示页面未发生变化
if ((ex.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotModified)
{
changed = false;
}
else
{
throw ex;
}
}
return changed;
} 需要注意的是,在网页内容没有发生变化时,会抛出异常,状态码只能在异常信息中获取。另外在返回200状态码时,有时候并不表示页面发生了变化,因为有些服务器不识别请求中的lastModifiedSince内容。经过实际项目的实践,发现大部分的静态页面内容,都能够通过该方法判断。
如有更好的方法,特别是判断动态页面是否更新的方法,欢迎交流。
这个状态码就是304(Not Modified),对于这个代码的解释是"如果客户端发送了一个带条件的 GET 请求且该请求已被允许,而文档的内容(自上次访问以来或者根据请求的条件)并没有改变,则服务器应当返回这个状态码"。很明显通过这个解释,我们就明白了其实现的机理。我们要做的事情,仅仅是在发送请求时将上次访问的时间添加到header中,然后根据服务器返回的状态码进行判断。通常,在网页发生变化时,服务器会返回状态码200,而未发生变化则返回304。
dotnet在网络传输这块已经提供了完善的API,接下来请看具体的实现方式。在这个例子中,通过访问国家统计局的banner页面(http://www.stats.gov.cn/top.html)来演示,分别检查3天前和3个月前该页面是否发生了变化。
static void Main(string[] args)
{
string url = "http://www.stats.gov.cn/top.html";
// 检查3天前网页是否发生了变化
DateTime modifiedSince = DateTime.Now.AddDays(-3);
// 输出false
Console.WriteLine(PageHasChanged(url, modifiedSince));
// 检查3个月前是否发生了变化
modifiedSince = DateTime.Now.AddMonths(-3);
// 输出true
Console.WriteLine(PageHasChanged(url, modifiedSince));
}
private static bool PageHasChanged(string url, DateTime modifiedSince)
{
bool changed = false;
// 设置请求信息
HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
// 最关键的一项设置 将请求的IfModifiedSince设置为指定的时间
request.IfModifiedSince = modifiedSince;
HttpWebResponse response = null;
try
{
response = request.GetResponse() as HttpWebResponse;
// 根据返回的状态码判断内容是否发生了变化
// 200表示页面发生了变化
if (response.StatusCode == HttpStatusCode.OK)
{
changed = true;
}
else if (response.StatusCode == HttpStatusCode.NotModified)
{
changed = false;
}
response.Close();
}
catch (WebException ex)
{
// 对于没有发生变化的页面 通常会通过抛出异常的方式提示页面未发生变化
if ((ex.Response as HttpWebResponse).StatusCode == HttpStatusCode.NotModified)
{
changed = false;
}
else
{
throw ex;
}
}
return changed;
} 需要注意的是,在网页内容没有发生变化时,会抛出异常,状态码只能在异常信息中获取。另外在返回200状态码时,有时候并不表示页面发生了变化,因为有些服务器不识别请求中的lastModifiedSince内容。经过实际项目的实践,发现大部分的静态页面内容,都能够通过该方法判断。
如有更好的方法,特别是判断动态页面是否更新的方法,欢迎交流。
相关文章推荐
- 利用Http状态码检查网页内容是否更新 提取网页有用的很
- ObjC利用正则表达式抓取网页内容(网络爬虫)
- asp中利用xmlhttp抓取网页内容的代码
- [Python]网络爬虫(二):利用urllib2通过指定的URL抓取网页内容
- Android检查更新(是否强制更新)
- 【JavaScript】利用正则表达式检查输入框输入的是否为网址
- 利用HttpModule 检查用户是否有权限打开指定的网址
- jquery检查某个元素在网页上是否存在?
- 利用正则表达式限制网页表单里的文本框输入内容
- 利用HtmlParser来提取网页内容
- 利用htmlparser抓取网页内容(一)
- scrapy框架中利用xpath获取网页内容为空,而xpath书写完全正确
- 利用JavaScript检查用户注册信息是否正确,在以下情况不满足时报错并阻止提交表单
- [VB.NET]我打开网页的时候会弹出一个安全信息,然后出现:本页包含安全能容和不安全内容,是否显示不安全内容”请达人指教一下怎么删除这个提示
- [VB.NET]高手帮忙,水晶报表显示在网页上的内容不更新,在线等,只有40分了
- javascript如何检查网页元素是否包含某个特定字符串
- android 检查软件是否有更新版本
- 网络爬虫(二):利用urllib2通过指定的URL抓取网页内容
- 利用java获取网页内容
- 正文抽取-利用curl获取网页内容