C#简易蜘蛛爬虫程序

http://www.cnblogs.com/taobox/archive/2012/09/18/2691694.html

 

C#简易蜘蛛爬虫程序
开发爬虫程序首先要先得到Web页面的HTML代码,微软已经为我们提供了很方便的方法,我们可以用WebClient或WebRequest、HttpWebResponse来很容易的得到网站页面的HTML代码。最后已经提供源码下载。

 

先举例用WebClient得到HTML代码的方法。

复制代码
    private string getHTML(string strUrl,Encoding encoding)
    {
        Uri url = new Uri(strUrl);
        WebClient wc = new WebClient();
        wc.Encoding = encoding;
        Stream s = wc.OpenRead(url);
        StreamReader sr = new StreamReader(s, encoding);
        return sr.ReadToEnd();
    }
复制代码

 

调用的时候需要知道页面的编码方式,后面会给大家举个不需要知道编码方式的例子。先看一下调用的方法:

string html = getHTML("http://www.baidu.com", Encoding.GetEncoding("GB2312"));

 

 

接下来就是重点了,用WebRequest、HttpWebResponse来获取页面的HTML代码,而且只需要传递进去一个URL就可以了,编码方式可以由程序来分析,虽然还不太完美,但大部分网站都能识别出来。

先用WebRequest初始化一个实列,然后用GetResponse请求得到的响应返回给HttpWebResponse,通过response.StatusDescription就可以得到编码方式的代码,通过分析得到我们需要的网页编码方式,最后将HTML代码读出来就可以了。

复制代码
    private void getHTMLbyWebRequest(string strUrl)
    {
        Encoding encoding = System.Text.Encoding.Default;
        WebRequest request = WebRequest.Create(strUrl);
        request.Credentials = CredentialCache.DefaultCredentials;
        HttpWebResponse response = (HttpWebResponse)request.GetResponse();
        if (response.StatusDescription.ToUpper() == "OK")
        {
            switch (response.CharacterSet.ToLower())
            {
                case "gbk":
                    encoding = Encoding.GetEncoding("GBK");//貌似用GB2312就可以
                    break;
                case "gb2312":
                    encoding = Encoding.GetEncoding("GB2312");
                    break;
                case "utf-8":
                    encoding = Encoding.UTF8;
                    break;
                case "big5":
                    encoding = Encoding.GetEncoding("Big5");
                    break;
                case "iso-8859-1":
                    encoding = Encoding.UTF8;//ISO-8859-1的编码用UTF-8处理,致少优酷的是这种方法没有乱码
                    break;
                default:
                    encoding = Encoding.UTF8;//如果分析不出来就用的UTF-8
                    break;
            }
            this.Literal1.Text = "Lenght:" + response.ContentLength.ToString() + "<br>CharacterSet:" + response.CharacterSet + "<br>Headers:" + response.Headers + "<br>";
            Stream dataStream = response.GetResponseStream();
            StreamReader reader = new StreamReader(dataStream, encoding);
            string responseFromServer = reader.ReadToEnd();
            this.TextBox2.Text = responseFromServer;
            FindLink(responseFromServer);
            this.TextBox2.Text = ClearHtml(responseFromServer);
            
            reader.Close();
            dataStream.Close();
            response.Close();
        }
        else
        {
            this.TextBox2.Text = "Error";
        }
    }
复制代码

 

这样网页的HTML代码就已经得到了,接下来就是处理链接和过滤掉没用的HTML代码并把文本内容保留下来了。

 

已经可以得到页面的HTML代码,接下来需要对HTML代码分析,得到里面所有的链接和过滤掉没用的HTML代码,把文字内容保留下来。

分析HTML代码,通过正规表达式将链接和链接的文字内容保存下来。

复制代码
    private void FindLink(string html)
    {
        this.TextBox3.Text="";
        List<string> hrefList = new List<string>();//链接
        List<string> nameList = new List<string>();//链接名称

        string pattern = @"<a\s*href=(""|')(?<href>[\s\S.]*?)(""|').*?>\s*(?<name>[\s\S.]*?)</a>";
        MatchCollection mc = Regex.Matches(html, pattern);
        foreach (Match m in mc)
        {
            if (m.Success)
            {
                //加入集合数组
                hrefList.Add(m.Groups["href"].Value);
                nameList.Add(m.Groups["name"].Value);
                this.TextBox3.Text += m.Groups["href"].Value + "|" + m.Groups["name"].Value + "\n";
            }
        }
    }
复制代码

这个方法只实现简单的找到链接,并没有过滤掉#或javascript:void(0)这样的内容。

 

接下要过滤掉没有用的HTML代码,保留文字内容,基本还是正规表达式,网上还有很多种方法,写的正规的HTML页面都可以正常过滤掉,不过对于那些代码都不成对的、不按常理出牌的网站,我就很无语了……

复制代码
    public string ClearHtml(string text)//过滤html,js,css代码
    {
        text = text.Trim();
        if (string.IsNullOrEmpty(text))
            return string.Empty;
        text = Regex.Replace(text, "<head[^>]*>(?:.|[\r\n])*?</head>", "");
        text = Regex.Replace(text, "<script[^>]*>(?:.|[\r\n])*?</script>", "");
        text = Regex.Replace(text, "<style[^>]*>(?:.|[\r\n])*?</style>", "");
        
        text = Regex.Replace(text, "(<[b|B][r|R]/*>)+|(<[p|P](.|\\n)*?>)", ""); //<br> 
        text = Regex.Replace(text, "\\&[a-zA-Z]{1,10};", "");
        text = Regex.Replace(text, "<[^>]*>", "");

        text = Regex.Replace(text, "(\\s*&[n|N][b|B][s|S][p|P];\\s*)+", ""); //&nbsp;
        text = Regex.Replace(text, "<(.|\\n)*?>", string.Empty); //其它任何标记
        text = Regex.Replace(text, "[\\s]{2,}", " "); //两个或多个空格替换为一个

        text = text.Replace("'", "''");
        text = text.Replace("\r\n", "");
        text = text.Replace("  ", "");
        text = text.Replace("\t", "");
        return text.Trim();
    }
复制代码

 

最后再加个通过URL分析IP地址的方法,有些域名做均衡负载的都可以分析出多个IP,不过只能在本地运行,放IIS上需要完整的信任级别,关于信任级别的说明请点这里

复制代码
    private void IPAddresses(string url)
    {
        url = url.Substring(url.IndexOf("//") + 2);
        if (url.IndexOf("/") != -1)
        {
            url = url.Remove(url.IndexOf("/"));
        }
        this.Literal1.Text += "<br>" + url;
        try
        {
            System.Text.ASCIIEncoding ASCII = new System.Text.ASCIIEncoding();
            IPHostEntry ipHostEntry = Dns.GetHostEntry(url);
            System.Net.IPAddress[] ipaddress = ipHostEntry.AddressList;
            foreach (IPAddress item in ipaddress)
            {
                this.Literal1.Text += "<br>IP:" + item;
            }
        }
        catch { }
    }
复制代码

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值