微信小程序+.NET(七) 最简单的.NET爬虫

  最简单的.NET爬虫

  我的另一篇音视频编码转换:https://blog.csdn.net/jinglell/article/details/99677371
  我给自己写的这个爬虫叫“最简单的.NET爬虫”,因为它实在是太过简单,当然最后的实现是简单的,前期的搜集资料和尝试其实也花了不少时间。
  首先,我先到网上找了几个帖子,尤其是这位专门搞携程的老哥:https://www.cnblogs.com/jjg0519/p/6702747.html直接百度“爬虫 携程”就可以找到这位大神了,我之前的爬虫都是没有接口需求的,就是数据分析课程需要爬取一些数据,直接用Python脚本就可以,反正最后只需要表格数据,而通过这次的查找,我对.NET爬虫印象.挺好的
在这里插入图片描述
说是速度快,什么什么的,反正看不太懂<_<,不过我对这个速度没什么太强的感受,因为我自己就是一次爬取一个页面而已,反而因为.NET没有beautifulsoup的存在,在gbk文本编码问题上卡了很长一段时间。
下面说我遇到的问题:

  1.发起request请求
这里.NET里一般有两种,webclienthttpclient,httpclient在我的4.6.1版本需要添加引用,引用新的System.NET.HTTP,webclient不需要,下面是我一开始用的httpclient:

//HttpClient httpClient = new HttpClient();
            //HttpResponseMessage res = httpClient.GetAsync(url).Result;
            //if (res.IsSuccessStatusCode)
            //{
            //Task<string> t = res.Content.ReadAsStringAsync();
                //string content = t.Result;
                //content = EnCodeCovert(content);

这个形式我弄到最后是失败的,我记得应该是因为最后一行的原因导致乱码,所以最后舍弃了。
我现在采用的是WebClient,

System.Net.WebClient client = new System.Net.WebClient();
byte[] page = client.DownloadData(url);
string content = System.Text.Encoding.GetEncoding("GBK").GetString(page);

我自己感觉在request没有那么多需求,比如异步,而且request的网站并没有做一些拦截处理和一些验证时,WebClient更为简洁

  2.文本编码问题
这个问题比上一个更耗费时间,我爬取的网站是gbk格式的,爬过来是乱码,然后我上网找了采用了如下方式进行转码:

private static string EnCodeCovert(string value)
{
    System.Text.Encoding srcEncode = System.Text.Encoding.GetEncoding("gb2312");
    System.Text.Encoding convToEncode = System.Text.Encoding.Default;
    byte[] bytes = srcEncode.GetBytes(value);
    System.Text.Encoding.Convert(srcEncode, convToEncode, bytes, 0, bytes.Length);
    return convToEncode.GetString(bytes);
}

private static string EnCodeCovert2(string str)
{
    byte[] buffer = Encoding.Default.GetBytes(str);
    byte[] buffers = Encoding.Convert(Encoding.Default, Encoding.UTF8, buffer);
    return  Encoding.UTF8.GetString(buffers);
}

事实又一次证明这玩意多么难搞,我当时还是用的httpclient,然后已经对数据通过正则表达式提取了乱码的gbk字符串,通过上述却怎么也转换不出来中文,最后从网上找了上述的webclient方式后,再对网页html数据直接解码再正则提取文本,最后实现了我的需求。
现在分析,我的总结就是,request返回的数据不要是字符串,而是字节流最好,然后直接对返回的字节流依据GBK格式转化成字符串就可以了。我对HttpClient了解少,我想应该也是有方法接收字节流的,那样就可以转码了。

  3.正则表达式匹配
参考上面那位搞携程的前辈的写法:

var linkChapter = Regex.Matches
(
    content,
    @"<div[^>]+class=""nr_title""\sid=""nr_title"">(?<text>.*?)</div>",
    //@"""><a[^>]+href=""*(?<href>/hotel/[^>\s]+)""\s*data-dopost[^>]*><span[^>]+>.*?</span>(?<text>.*?)</a>"
    //"<a     href=     <href>/hotel/[    ]            >  <text>             </a>",
    //<div class="nr_title" id="nr_title"> 第一千八百二十三章 封界十万年!(终)</div>
    RegexOptions.IgnoreCase
);
foreach (Match match in linkChapter)
{
    novel.Chapter += match.Groups["text"].Value;
}

  4.文本换行、空格
这个问题可以在上述正则匹配时进行处理:插入一个特殊字符串("ENTER")做间隔符

foreach (Match match in linksContext)
{
    novel.Context += match.Groups["text"].Value+ "ENTER";
}

在小程序端可以对文本切割或是替换间隔符为“\n&emsp;&emsp;”
这里有一个小问题:空格在不同场景下的书写:
1’正则表达式:
\s
2’HTML:
一个中文字符| |&emsp;
半个中文字符| |&ensp;
正常的空格| |&nbsp;

最后附上我的整个function

public static string GetContext(string url)
{
    var novel = new Novel();
    System.Net.WebClient client = new System.Net.WebClient();
    byte[] page = client.DownloadData(url);
    string content = System.Text.Encoding.GetEncoding("GBK").GetString(page);
    //HttpClient httpClient = new HttpClient();
    //HttpResponseMessage res = httpClient.GetAsync(url).Result;
    //if (res.IsSuccessStatusCode)
    //{
    //Task<string> t = res.Content.ReadAsStringAsync();
        //string content = t.Result;
        //content = EnCodeCovert(content);
        var linkChapter = Regex.Matches
        (
            content,
            @"<div[^>]+class=""nr_title""\sid=""nr_title"">(?<text>.*?)</div>",
            //@"""><a[^>]+href=""*(?<href>/hotel/[^>\s]+)""\s*data-dopost[^>]*><span[^>]+>.*?</span>(?<text>.*?)</a>"
            //"<a     href=     <href>/hotel/[    ]            >  <text>             </a>",
            //<div class="nr_title" id="nr_title"> 第一千八百二十三章 封界十万年!(终)</div>
            RegexOptions.IgnoreCase
        );
        var linkBook = Regex.Matches
        (
            content,
            @"<title>(?<text>.*?)</title>",
            //@"<h1><a\s*id=""bookname"">(?<text>.*?)</a>",
            //@"""><a[^>]+href=""*(?<href>/hotel/[^>\s]+)""\s*data-dopost[^>]*><span[^>]+>.*?</span>(?<text>.*?)</a>"
            //"<a     href=     <href>/hotel/[    ]            >  <text>             </a>",
            //<h1><a href="/info/78738/" id="bookname">超级武神</a></h1>
            RegexOptions.IgnoreCase
        );
        var linksContext = Regex.Matches
        (
            content,
            @"(&nbsp;){4}(?<text>.*?)<br />",
            //"<a     href=     <href>/hotel/[    ]            >  <text>             </a>",
            //&nbsp;&nbsp;&nbsp;&nbsp;“聂天!”<br />
            RegexOptions.IgnoreCase
        );
        foreach (Match match in linkBook)
        {
            novel.Book += match.Groups["text"].Value.Split('-')[1];
        }
        foreach (Match match in linkChapter)
        {
            novel.Chapter += match.Groups["text"].Value;
        }
        foreach (Match match in linksContext)
        {
            novel.Context += match.Groups["text"].Value+ "ENTER";
        }
        //novel.Context = System.Web.HttpUtility.UrlEncode(novel.Context, System.Text.Encoding.GetEncoding("gb2312"));
        //var bytes = System.Text.Encoding.GetEncoding("GBK").GetBytes(novel.Context);
        //novel.Context = System.Text.Encoding.UTF8.GetString(bytes);
        //novel.Context = EnCodeCovert(novel.Context);
        return Newtonsoft.Json.JsonConvert.SerializeObject(novel);
    //}
    //return string.Empty;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值