惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
L
LINUX DO - 热门话题
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
雷峰网
雷峰网
aimingoo的专栏
aimingoo的专栏
博客园_首页
MongoDB | Blog
MongoDB | Blog
V
V2EX
GbyAI
GbyAI
量子位
Microsoft Azure Blog
Microsoft Azure Blog
有赞技术团队
有赞技术团队
G
Google Developers Blog
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
S
SegmentFault 最新的问题
O
OpenAI News
N
News and Events Feed by Topic
博客园 - Franky
爱范儿
爱范儿
Forbes - Security
Forbes - Security
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V2EX - 技术
V2EX - 技术
Application and Cybersecurity Blog
Application and Cybersecurity Blog
N
News and Events Feed by Topic
N
News | PayPal Newsroom
Schneier on Security
Schneier on Security
Cloudbric
Cloudbric
Security Archives - TechRepublic
Security Archives - TechRepublic
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Recent Commits to openclaw:main
Recent Commits to openclaw:main
人人都是产品经理
人人都是产品经理
P
Privacy International News Feed
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
阮一峰的网络日志
阮一峰的网络日志
D
DataBreaches.Net
Last Week in AI
Last Week in AI
罗磊的独立博客
Spread Privacy
Spread Privacy
Recent Announcements
Recent Announcements
The Cloudflare Blog
Google DeepMind News
Google DeepMind News
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
Y
Y Combinator Blog
J
Java Code Geeks
I
Intezer

博客园 - 卢春城

Lesktop开源IM移动端:接入LayIM移动端UI 开源企业即时通讯和在线客服 开源企业即时通讯和在线客服 在SQL Server中对视图进行增删改 WebBrowser介绍——Javascript与C++互操作 开源WebOS 一步一步打造WebIM(4)——Comet的特殊之处 一步一步打造WebIM(3)——性能测试 在线CHM阅读器(2)——文件提取及关键文件解析 一步一步打造WebIM(2)——消息缓存 在线CHM阅读器(1)——CHM文件格式概述 一步一步打造WebIM(1) 谈谈网站设计时图片的使用 如何开发HTML编辑器 Variable控件[更新至1.3]--在客户端和服务器之间传送变量 公交车路线查询系统后台数据库设计--换乘算法改进与优化 公交车路线查询系统后台数据库设计 公交车路线查询系统后台数据库设计--引入步行路线 远程控制程序
网页信息抓取
卢春城 · 2010-05-18 · via 博客园 - 卢春城

之前做聊天室时,由于在聊天室中提供了新闻阅读的功能,写了一个从网页中抓取信息(如最新的头条新闻,新闻的来源,标题,内容等)的类,本文将介绍如何使用这个类来抓取网页中需要的信息。本文将以抓取博客园首页的博客标题和链接为例:

image

上图显示的是博客园首页的DOM树,显然只需提取出class为post_item的div,再重中提取出class为titlelnk的a标志即可。这样的功能可以通过以下函数来实现:

/// <summary>
/// 在文本html的文本查找标志名为tagName,并且属性attrName的值为attrValue的所有标志
/// 例如:FindTagByAttr(html, "div", "class", "demo")
/// 返回所有class为demo的div标志
/// </summary>
public static List<HtmlTag> FindTagByAttr(String html, String tagName, String attrName, String attrValue)
{
    String format = String.Format(@"<{0}\s[^<>]*{1}\s*=\s*(\x27|\x22){2}(\x27|\x22)[^<>]*>", tagName, attrName, attrValue);
    return FindTag(html, tagName, format);
}

public static List<HtmlTag> FindTag(String html, String name, String format)
{
    Regex reg = new Regex(format, RegexOptions.IgnoreCase);
    Regex tagReg = new Regex(String.Format(@"<(\/|)({0})(\s[^<>]*|)>", name), RegexOptions.IgnoreCase);

    List<HtmlTag> tags = new List<HtmlTag>();
    int start = 0;

    while (true)
    {
        Match match = reg.Match(html, start);
        if (match.Success)
        {
            start = match.Index + match.Length;
            Match tagMatch = null;
            int beginTagCount = 1;

            while (true)
            {
                tagMatch = tagReg.Match(html, start);
                if (!tagMatch.Success)
                {
                    tagMatch = null;
                    break;
                }
                start = tagMatch.Index + tagMatch.Length;
                if (tagMatch.Groups[1].Value == "/") beginTagCount--;
                else beginTagCount++;
                if (beginTagCount == 0) break;
            }

            if (tagMatch != null)
            {
                HtmlTag tag = new HtmlTag(name, match.Value, html.Substring(match.Index + match.Length, tagMatch.Index - match.Index - match.Length));
                tags.Add(tag);
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }
    }

    return tags;
}

有了以上函数,就可以提取需要的HTML标志了,要实现抓取,还需要一个下载网页的函数:

public static String GetHtml(string url)
{
    try
    {
        HttpWebRequest req = HttpWebRequest.Create(url) as HttpWebRequest;
        req.Timeout = 30 * 1000;
        HttpWebResponse response = req.GetResponse() as HttpWebResponse;
        Stream stream = response.GetResponseStream();

        MemoryStream buffer = new MemoryStream();
        Byte[] temp = new Byte[4096];
        int count = 0;
        while ((count = stream.Read(temp, 0, 4096)) > 0)
        {
            buffer.Write(temp, 0, count);
        }

        return Encoding.GetEncoding(response.CharacterSet).GetString(buffer.GetBuffer());
    }
    catch
    {
        return String.Empty;
    }
}

以下以抓取博客园首页的文章标题和链接为例,介绍如何使用HtmlTag类来抓取网页信息:

class Program
{
    static void Main(string[] args)
    {
        String html = HtmlTag.GetHtml("http://www.cnblogs.com");
        List<HtmlTag> tags = HtmlTag.FindTagByAttr(html, "div", "id", "post_list");
        if (tags.Count > 0)
        {
            List<HtmlTag> item_tags = tags[0].FindTagByAttr("div", "class", "post_item");
            foreach (HtmlTag item_tag in item_tags)
            {
                List<HtmlTag> a_tags = item_tag.FindTagByAttr("a", "class", "titlelnk");
                if (a_tags.Count > 0)
                {
                    Console.WriteLine("标题:{0}", a_tags[0].InnerHTML);
                    Console.WriteLine("链接:{0}", a_tags[0].GetAttribute("href"));
                    Console.WriteLine("");
                }
            }
        }
    }
}

运行结果如下:

image

源代码下载