• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
内蒙古峰回路转armyfeng
博客园    首页    新随笔    联系   管理    订阅  订阅

[导入]网络蜘蛛研究之总体设计及信息获取

这几天在做书库系统,加了几天也陆续加了150多本书了,可是这样加还是会花费很多时间! 有没有好的办法可以自动加书呢? 这几天百度了几个免费在线电子书的网站,发现他们内容归类的比较简单, 完全可以用网络蜘蛛"盗取"过来. 于是萌发了自己写一个网络蜘蛛程序的想法. 而且把抓取的书自动保存到数据库里. 而每天我只要检查下,然后把抓取的书发布就行了.

编写一个这样的蜘蛛程序,一般的顺序是:

1. 根据url 获取网页内容.

2. 分析获取的网页内容, 进行信息分类,并且分析出url, 进行下一次获取网页.

3. 将归类之后的信息保存进数据库.

难点: 分析出url, 应用多线程提高程序效率.

根据以上几点,我特将此问题分解成若干个子问题,一一突破. 如果用递归的形式来思考这个问题,则只要考虑如何分析单一页面,并且假定待访问url栈为其他线程共享资源. 这里为什么用栈而不用队列? 原因就是先进栈的url应该是与正在处理的url联系最紧密的, 这样有利于相同信息的比较!

while(待访问的url栈为空?){

出栈.

激活线程.

}

线程(){

根据url抓取内容;

获取信息:保存信息

获取url:将url置入待访问栈.

}

由上面可以看出,解决了单一线程访问某个单一页面这个难题, 则整个蜘蛛程序核心的部分也就完成. 在这里我将采用C# 来开发这个蜘蛛程序,原因有3, C#是我比较熟悉的一种编程语言,而且.net环境比较熟悉. 二. .net 内置了http访问功能,这样url获取网页内容就非常好解决. 三 C#本身就支持多线程,开发多线程的程序将变得非常简单! 所以基于以上几点考虑, 采用C#来做这个蜘蛛是最合适不过的了. 在我的博客上转载了几篇关于蜘蛛以及获取网页信息的文章, 个人感觉非常不错. 我也主要是研究那几篇帖子来完成此程序的. 当然能不能达到预期的效果, 就看未来几天的努力了!

今天将抓取信息的部分,封装进了我的luotongUnit类库, 类的名字为 NetSpider ,这个类我将设计成具有以下几个功能:

1. 通过url获取网页内容,并返回string.

2.连接分析. 通过传入的 字符串xx 分析出内容(xx),以及连接(link) 并返回. 此处打算设置成一个 连接的 struct.

3. 根据抓取的内容,返回去掉标签及首尾标记符的 内容.

4. 其他功能暂定! 毕竟现在还不能知道具体的细分规则!

现在此类以具有根据url获取网页内容的功能, 并且写了简单的demo程序测试.

namespace luotongUnit
{
///


/// 主要用于获取Internet上的信息。
/// 1、根据Url获取文本及2进制内容。
/// 2、Html分析。
/// 3、还有其他的功能暂时没有想到!
/// 2006.1.10
///
///

public class NetSpider
{
public static string Get_Http(string url,int timeout)
{
try
{

HttpWebRequest myReq = (HttpWebRequest)HttpWebRequest.Create(url) ;

myReq.Timeout = timeout;
HttpWebResponse HttpWResp = (HttpWebResponse)myReq.GetResponse();

Stream myStream = HttpWResp.GetResponseStream () ;

StreamReader sr = new StreamReader(myStream,Encoding.Default);
StringBuilder strBuilder = new StringBuilder();
while (sr.Peek()!=-1)
{
strBuilder.Append(sr.ReadLine()+"\r\n");
}

return strBuilder.ToString();
}
catch(Exception exp)
{
return "错误:" + exp.Message ;
}
}
}
}

demo程序调用为:

private void btnOk_Click(object sender, System.EventArgs e)
{
string strUrl="";
string strDir="";
if (txtUrl.Text!=Url_Default) strUrl=txtUrl.Text;
if(txtDir.Text!=Dir_Default) strDir=txtDir.Text;
strUrl=strUrl.ToLower();
if(strUrl.IndexOf("http://")==-1) strUrl="http://"+strUrl;
txtResult.Text=NetSpider.Get_Http(strUrl,10000);
}

到现在, 已经完成了此蜘蛛程序的 获取页面功能,这也从根本上解决了获取内容,保存内容2个问题( 因为保存内容到数据库是我的强项). 在接下来的几天里,我将陆续完成html分析的功能,并且将功能细分,最终完善 NetSpider 类.

[转]网络蜘蛛研究之正则表达式


在昨天发表的那篇网络蜘蛛研究中提到了对获取html进行分析这一问题. 开始想用字符判断来完成,后来发现这样编程的工作太过于巨大. 而以前用asp处理ubb码的时候用到过正则表达式, 这对于分析html代码非常有帮助,所以想将html的分析转换为特定的正则表达式. 其实对于html的分析,我们可以引用编译原理里的"遍"这个概念. 你想要一次处理完这么多信息是不可能, 需要一遍一遍的过滤. 而每一遍完成对特定html标签的处理. 于是基本思路定于:

第1遍: 读取特定网站的特征文件! 在开始过程中,我个人认为可以将首页url以及特征文件做为输入项. 这个特征文件应该包含: 从哪个特殊字符开始过滤. 而只留下与内容结合最紧密的html源代码.

第2遍: 过滤掉背景,布局等布局标签.

第3遍: 从省下的代码中过滤出 url, 主题信息. 以及图片url

上面3遍其实是大致的分步, 而每一步又可以有若干个小步骤. 如果从这个思路出发, 那么我的NetSpider类其他的功能就应该是对 常用html进行过滤的静态函数. 这些函数主要供第2遍及第3遍使用. 而第一遍应该根据过滤文件来来写相应的程序. 对于这种复杂的过滤, 正则表达式是最好的方法! 在我的blog中,我转载了2篇关于正则表达式的文章,相信大家看了这2篇文章后应该对正则的强大功能有个大概的了解.

下面我介绍下C#里使用正则需要用到的类. 首先C#的正则表达式需要调用System.Text.RegularExpressions 命名空间.

下面我以一个简单的例子说明如何使用正则. 此例子是昨天那个抓取函数的正则改良版.

private void btnOk_Click(object sender, System.EventArgs e)
{
string strUrl="";
string strDir="";
if (txtUrl.Text!=Url_Default) strUrl=txtUrl.Text;
if(txtDir.Text!=Dir_Default) strDir=txtDir.Text;
Regex reg=new Regex("^http://",RegexOptions.IgnoreCase|RegexOptions.Compiled);
Match mResult=reg.Match(strUrl);
if(!mResult.Success) strUrl="http://"+strUrl;
txtResult.Text=NetSpider.Get_Http(strUrl,10000);
}

可以对比下昨天的代码。 其中判断输入的连接是否以 http:// 开头这里改成了用正则表达式来判断。而其中的RegexOptions.IgnoreCase|RegexOptions.Compiled 代表忽略大小写并且编译改正则表达式。

至此对于正则表达式的初步探索也就告一段落了,其实更深入的正则表达式应用可以看.net framework 的帮助文档。 其中有一段对于网络很实用的正则代码:

void DumpHrefs(String inputString)
{
Regex r;
Match m;

r = new Regex("href\\s*=\\s*(?:\"(?<1>[^\"]*)\"|(?<1>\\S+))",
RegexOptions.IgnoreCase|RegexOptions.Compiled);
for (m = r.Match(inputString); m.Success; m = m.NextMatch())
{
Console.WriteLine("Found href " + m.Groups[1] + " at "
+ m.Groups[1].Index);
}
}
以上这个代码可以很方便的进行 超连接提取。


文章来源:http://www.codeguru.cn/ShowThread.aspx?PostID=1309
posted @ 2006-09-24 16:49  老冯  阅读(341)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3