雷达智富

首页 > 内容 > 程序笔记 > 正文

程序笔记

使用htmlagilitypack+xpath抓取网页内容示例

2024-10-16 32

本文使用htmlagilitypack+xpath抓取网页内容示例,用简单的例子展示如何使用htmlagilitypack抓取网页,可以用来做数据采集等功能。

用htmlagilitypack+xpath抓取网页内容示例源码下载

首先在nuget中获取htmlagilitypack最新版本,当前最新版本是1.8.5稳定版。

本文以抓取汽车之家车家号的文章为例子,抓取链接地址为https://chejiahao.autohome.com.cn/info/2606070#pvareaid=2808158

为了直观显示,我创建了一个winform应用,并用几个简单的控件展示数据。

使用htmlagilitypack首先要了解XPath语法,我们查看网页的源码发现正文内容在class为article-content example的div里面,所以要从真个html里面找到class=article-content example的div节点,用XPath语法表示就是//div[@class='article-content example'],注意,这里必须是class='article-content example',如果写class='article-content'是无法正确找到该节点的。

以下是获取html和网页标题和p标签内容的简单示例代码:

private void button1_Click(object sender, EventArgs e)
{
    string url = tbUrl.Text.Trim();
    HtmlWeb hw = new HtmlWeb();
    HtmlDocument hd = hw.Load(url);
    richTextBox1.Text = hd.Text;
    var title = hd.DocumentNode.SelectSingleNode("//title");
    if (title != null) {
        tbTitle.Text = title.InnerText;
    }
    string article = string.Empty;
    var contentDiv = hd.DocumentNode.SelectSingleNode("//div[@class='article-content example']");
    if (contentDiv != null) {
        var pList = contentDiv.SelectNodes(".//p");
        if (pList != null) {
            foreach (var p in pList) {
                if (!string.IsNullOrWhiteSpace(p.InnerText)) {
                    article += p.InnerText + "\r";
                }
            }
        }
    }
    richTextBox2.Text = article.Trim();
}

代码中首先找到了class='article-content example'的div节点,然后在这个节点下找p子节点,找到p子节点后遍历p子节点,把p节点下的文字取出来,然后显示在richtextbox2中,运行结果如下图所示:

那么如果我们想顺序把图片和文字内容都采集下来该怎么办呢?我们再分析一下该页面的html代码,不难发现,在内容div下的子节点里有两种div,一种是<div ahe-role="image" class="ahe__area ahe__block ahe__image">,这个div里面是图片,还有一种是<div ahe-role="text" class="ahe__area ahe__block ahe__text">,这个div里面包含的是段落文字。

那么我们可以遍历内容div下的子节点,然后根据子节点的ahe-role属性判断是图片还是文字,如果是图片就再取该节点下的图片标签,并且取图片标签的url属性,值得注意的是,该页面图片使用了懒加载,所以图片url在img标签的data-original属性上。如果是段落文字就取该子节点下的p标签里的文字内容。具体实现代码如下:

private void button2_Click(object sender, EventArgs e)
{
    string url = tbUrl.Text.Trim();
    HtmlWeb hw = new HtmlWeb();
    HtmlDocument hd = hw.Load(url);
    richTextBox1.Text = hd.Text;
    var title = hd.DocumentNode.SelectSingleNode("//title");
    if (title != null)
    {
        tbTitle.Text = title.InnerText;
    }
    string article = string.Empty;
    var contentDiv = hd.DocumentNode.SelectSingleNode("//div[@class='article-content example']");
    if (contentDiv != null)
    {
        foreach (var child in contentDiv.ChildNodes) {
            //遍历内容div的子节点,找到ahe-role属性
            var role = child.Attributes.FirstOrDefault(x => x.Name == "ahe-role");
            if (role != null) {
                //如果属性值=image表示该节点内容为图片
                if (role.Value == "image")
                {
                    var images = child.SelectNodes(".//img");
                    if (images != null) {
                        foreach (var image in images) {
                            //图片使用懒加载,所以真实的图片地址在data-original属性上
                            var imageUrlAttr = image.Attributes.FirstOrDefault(x => x.Name == "data-original");
                            if (imageUrlAttr != null)
                            {
                                article += imageUrlAttr.Value + "\r";
                            }
                        }
                    }
                }
                //如果属性值=p表示该节点内容为文字
                else if (role.Value == "text") {
                    var pList = child.SelectNodes(".//p");
                    if (pList != null)
                    {
                        foreach (var p in pList)
                        {
                            if (!string.IsNullOrWhiteSpace(p.InnerText))
                            {
                                article += p.InnerText + "\r";
                            }
                        }
                    }
                }
            }
        }
    }
    richTextBox2.Text = article.Trim();
}

运行结果如下:

大家在实际编写代码的时候可以根据目标网页实际的html布局情况来使用恰当的规则抓取内容,通过这个办法可以方便的抓取网页上游泳的信息,实现一些爬虫类的功能了。

更新于:1个月前
赞一波!

文章评论

评论问答