Asp .Net Core网页数据爬取笔记

535 阅读3分钟

突然要用到地区数据,想到以前用python的Scrapy框架写过一个爬虫,于是打算直接去国家统计局把最新的地区数据抓取回来.本想只需要copy一下以前的代码,就可以得到新鲜出炉的数据,谁知打开以前的项目,脑子一片空白,一点印象都莫得.只恨当时没有做做笔记,写个博客啥的来加深一下影响.点子已经到这里来了,于是在.net core框架下再做了一点简单的爬取工作,并截取前面一部分,整理成文,方便以后回顾

 网页分析

网页数据抓取,第一步就是分析网页的结构,包括下面3种基本的信息:

    1网页编码格式:得到正确的编码格式是非常重要的,乱码可是会让人头疼

    2锁定目标节点:找到目标数据所在的节点

    3找寻多级依赖关系:例如本次爬取的省,市,区...,他们之间是存在依赖关系的,找到它们之间的关系才能获取完整的数据

网页的复杂程度不止于此,当遇到复杂的情况时,我们需要分析更多的信息,但就本次抓取而言,上述信息足以,所以不多做考虑

下面就以抓取省份或直辖市为例:

页面如下:

 查看页面元信息,页面编码格式为GB2312

 <META content="text/html; charset=gb2312" http-equiv=Content-Type> 

锁定数据所在的dom节点

<tr class='provincetr'>
    <td><a href='11.html'>北京市<br /></a></td>
    <td><a href='12.html'>天津市<br /></a></td>
    <td><a href='13.html'>河北省<br /></a></td>
    <td><a href='14.html'>山西省<br /></a></td>
    <td><a href='15.html'>内蒙古自治区<br /></a></td>
    <td><a href='21.html'>辽宁省<br /></a></td>
    <td><a href='22.html'>吉林省<br /></a></td>
    <td><a href='23.html'>黑龙江省<br /></a></td>
</tr>
<tr class='provincetr'>
    <td><a href='31.html'>上海市<br /></a></td>
    <td><a href='32.html'>江苏省<br /></a></td>
    <td><a href='33.html'>浙江省<br /></a></td>
    <td><a href='34.html'>安徽省<br /></a></td>
    <td><a href='35.html'>福建省<br /></a></td>
    <td><a href='36.html'>江西省<br /></a></td>
    <td><a href='37.html'>山东省<br /></a></td>
    <td><a href='41.html'>河南省<br /></a></td>
</tr>
<tr class='provincetr'>
    <td><a href='42.html'>湖北省<br /></a></td>
    <td><a href='43.html'>湖南省<br /></a></td>
    <td><a href='44.html'>广东省<br /></a></td>
    <td><a href='45.html'>广西壮族自治区<br /></a></td>
    <td><a href='46.html'>海南省<br /></a></td>
    <td> <a href='50.html'>重庆市<br /></a></td>
    <td><a href='51.html'>四川省<br /></a></td>
    <td><a href='52.html'>贵州省<br /></a></td>
</tr>
<tr class='provincetr'>
    <td><a href='53.html'>云南省<br /></a></td>
    <td><a href='54.html'>西藏自治区<br /></a></td>
    <td><a href='61.html'>陕西省<br /></a></td>
    <td><a href='62.html'>甘肃省<br /></a></td>
    <td><a href='63.html'>青海省<br /></a></td>
    <td><a href='64.html'>宁夏回族自治区<br /></a></td>
    <td><a href='65.html'>新疆维吾尔自治区<br /></a></td>
</tr>

找寻依赖关系

<a>标签的href属性的数字部分是进入下一级地域的关键

 数据抓取

在分析完页面结构后,下一步就可以开始我们的数据抓取

首先安装AngleSharp(Install-Package AngleSharp )的包,

AngleSharp :一个基于.NET(C#)开发的专门为解析xHTML源码的DLL组件(传送门),有了它我们就可以把得到的网页内容转换成规则的DOM,找寻我们的目标节点就变得非常简单

其次我所用的版本net core(2.2)不支持GB2312,如果直接操作,得到的只能是乱码,解决方法如下

    1安装System.Text.Encoding.CodePages包(Install-Package System.Text.Encoding.CodePages)

    2在启动类Starup的Configure方法中加入Encoding.RegisterProvider(CodePagesEncodingProvider.Instance)

做好上述的工作准备后,具体的代码如下

/// <summary>
/// 爬虫辅助类
/// </summary>
public static class SpiderHelper
{
    private static HtmlParser htmlParser = new HtmlParser();

    public static string GetHtml(string url)
    {
        HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

        HttpWebResponse response = (HttpWebResponse)request.GetResponse();

        try
        {
            Stream receive = response.GetResponseStream();

            StreamReader readStream = new StreamReader(receive, Encoding.GetEncoding("GB2312"));

            return readStream.ReadToEnd();
        }

        catch (Exception)
        {
            return "";
        }
    }

    /// <summary>
    /// 获取省份
    /// </summary>
    private static List<AreaViewModel> GetProvinces()
    {
        string html = GetHtml("http://www.stats.gov.cn/tjsj/tjbz/tjyqhdmhcxhfdm/2018/index.html");

        List<AreaViewModel> data = new List<AreaViewModel>();

        if (string.IsNullOrEmpty(html)) return data;

        //网页整体dom
        var document = htmlParser.ParseDocument(html);

        //目标元素dom,class为provincetr的tr元素下的a标签
        var list = document.QuerySelectorAll("tr.provincetr a");

        foreach (var item in list)
        {
            string name = item.TextContent;

            string id = item.GetAttribute("href").Replace(".html", "");

            data.Add(new AreaViewModel()
            {
                Id = id,
                Name = name,
                ParentId = "",
                Type = 2,
                Zip = ""
            });
        };

        return data;
    }
}

总结

上述的例子属于最基本的类型,对于更多网页数据的爬取,需要考虑的情况更加复杂,那时候就需要更加深入的剖析结构后通过更加复杂的技术来获取数据.但是最基本通用的原理还是和本文介绍的小例子相似