• 老蜗牛写采集:网络爬虫(二)


    短小精悍的xNet

          这个一个俄国牛人写的开源工具,为啥说他强悍了,因为他将所有Http协议的底层都实现了一遍,这有啥好处?只要你是写爬虫的,都会遇到一个让人抓狂的问题,就是明明知道自己Http请求头跟浏览器一模一样了,为啥还会获取不到自己想要的数据。这时你如果使用HttpWebReaquest,你只能调试到GetRespone,底层的字节流是调试不到了。所以必须得有个更深入的底层组件,方便自己调试。以下是xNet的开源地址:https://github.com/X-rus/xNet
    快速入门

    快速入门

          首先来一个读取cnblogs首页的案例,HttpWebRequest在上一篇已经举例,我们看看xNet是怎么写的

                using (var request = new xNet.HttpRequest())
                {
                    var html = request.Get("http://www.cnblogs.com").ToString();
                }
    

      增加http头,譬如:

      注意,默认的http头,建议用属性进行设置,譬如KeepAlive,Referer和UserAgent

      扩展的Http头,譬如Upgrade-Insecure-Requests,可以使用AddHeader方法进行设置譬如

                using (var request = new xNet.HttpRequest())
                {
                    request.AddHeader("Upgrade-Insecure-Requests", "1");
                    var html=request.Get("http://www.cnblogs.com").ToString();
                }
    

      当然有些方法使用AddHeader和设置属性值是一样的,例如:

          request.AddHeader("User-Agent","Mozilla/5.0 (Windows NT 6.3; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0");

          request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64; rv:49.0) Gecko/20100101 Firefox/49.0";

          request.UserAgent = xNet.Http.FirefoxUserAgent();

      当然不是所有值都可以使用AddHeader进行设置,譬如:Content-Type,这是POST时说明POST的数据类型,如果使用AddHeader会报错。如果你不知道那些可以手动设那些是不能的,参考xNet.HttpHeader的枚举值

        public enum HttpHeader
        {
            Accept = 0,
            AcceptCharset = 1,
            AcceptLanguage = 2,
            AcceptDatetime = 3,
            CacheControl = 4,
            ContentType = 5,
            Date = 6,
            Expect = 7,
            From = 8,
            IfMatch = 9,
            IfModifiedSince = 10,
            IfNoneMatch = 11,
            IfRange = 12,
            IfUnmodifiedSince = 13,
            MaxForwards = 14,
            Pragma = 15,
            Range = 16,
            Referer = 17,
            Upgrade = 18,
            UserAgent = 19,
            Via = 20,
            Warning = 21,
            DNT = 22,
            AccessControlAllowOrigin = 23,
            AcceptRanges = 24,
            Age = 25,
            Allow = 26,
            ContentEncoding = 27,
            ContentLanguage = 28,
            ContentLength = 29,
            ContentLocation = 30,
            ContentMD5 = 31,
            ContentDisposition = 32,
            ContentRange = 33,
            ETag = 34,
            Expires = 35,
            LastModified = 36,
            Link = 37,
            Location = 38,
            P3P = 39,
            Refresh = 40,
            RetryAfter = 41,
            Server = 42,
            TransferEncoding = 43,
        }
    

      

    xNet常用模块

      Post提交数据,偷懒,直接用官方的示例

    using (var request = new HttpRequest())
    {
        var reqParams = new RequestParams();
    
        reqParams["login"] = "neo";
        reqParams["password"] = "knockknock";
    
        string content = request.Post(
            "www.whitehouse.gov", reqParams).ToString();
    }
    

      等同于

                using (var request = new xNet.HttpRequest())
                {
                    var html = request.Post("www.whitehouse.gov",
                                            "login=neo&password=knockknock", "application/x-www-form-urlencoded").ToString();
                }
    

      

    application/x-www-form-urlencoded是form提交,默认是application/octet-stream,用于上传图片资源之类的,其实我觉得应该Form提交设置为默认,估计表单提交比较常用

    会使用Post之后,我们就可以做模拟登陆了,本来想举博客园登陆的例子,奈何dudu做了一系列的防自动登陆措施,所以也就作罢。其实如果真正想破其实也不难,很多公钥都写在页面上了,只要写一个RSA加密算法便可以得到加密后的用户名密码了。有兴趣的人可以研究一下。

    还有一个注意的地方,我比较推荐使用第一种方式,因为参数在内核里面就会UrlEncode了,如果自己拼凑地址的话,如果英文是没问题,但是中文或者其他文字就得UrlEncode一下了,譬如:"login="+System.Web.HttpUtility.UrlEncode("老蜗牛")+"&password=knockknock"
    这里要强烈抗议一下UrlEncode的方法应该放在System.Net的空间比较合适,因为做爬虫没必要使用System.Web命名空间,当然也有牛X的网友早就写了一个替代品
            //不用引用System.Web
            public static string ToUrlEncode(string strCode, Encoding encoding)
            {
                StringBuilder sb = new StringBuilder();
                byte[] byStr = encoding.GetBytes(strCode);
                System.Text.RegularExpressions.Regex regKey = new System.Text.RegularExpressions.Regex("^[A-Za-z0-9]+$");
                for (int i = 0; i < byStr.Length; i++)
                {
                    string strBy = Convert.ToChar(byStr[i]).ToString();
                    if (regKey.IsMatch(strBy))
                    {
                        //是字母或者数字则不进行转换
                        sb.Append(strBy);
                    }
                    else
                    {
                        sb.Append(@"%" + Convert.ToString(byStr[i], 16));
                    }
                }
                return (sb.ToString());
            }
    

      包含文件的表单

    using (var request = new HttpRequest())
    {
        var multipartContent = new MultipartContent()
        {
            {new StringContent("Bill Gates"), "login"},
            {new StringContent("qwerthahaha"), "password"},
            {new FileContent(@"C:windows_9_alpha.rar"), "file1", "1.rar"}
        };
    
        request.Post("www.microsoft.com", multipartContent).None();
    }
    

     设置Cookie值,这在模拟登陆和验证码会经常用到

                using (var request = new xNet.HttpRequest())
                {
                    request.Cookies = new xNet.CookieDictionary()
                    {
                        {"SERVERID", "9ffd301069c1081a14d128e0c97deda8|1478866092|1478862527"}
                    };
                    var html = request.Get("http://www.cnblogs.com").ToString();
                }
    

      等同于

                using (var request = new xNet.HttpRequest())
                {
                    request.AddHeader("Set-Cookie","SERVERID=9ffd301069c1081a14d128e0c97deda8|1478866092|1478862527;Path=/");
                    var html=request.Get("http://www.cnblogs.com").ToString();
                }
    

      使用Http代理

    var proxyClient = HttpProxyClient.Parse("127.0.0.1:8080");
    var tcpClient = proxyClient.CreateConnection("habrahabr.ru", 80);
    

      当然他还支持Socks4和Socks5,代理的好处不言而喻了。当然在挠头找服务端的童鞋可以上https://github.com/NewLifeX/X 里面有一个http代理服务器,非常强悍。不会弄的可以加石头的群。

      其他更多的功能就不一一举例了,有星期可以加群研究研究。

      一下篇会讲讲如何获取页面数据,主要是靠HtmlAgilityPack组件或者正则,两者各有各的优势。如果等不及可以看看我的好友老董写的一篇文章

    C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子)

      C#.NET开源项目、机器学习、足球赛事资料库 

      开源Q群:302961959

      足球研究技术群:142780296

     



  • 相关阅读:
    docker知识复习
    记住left join最简单的方式(转)
    ingress rewrite 配置文件的结构 + server_name和location这两条指令的配置来匹配要 虚拟主机
    PAM unable to dlopen(/lib/security/pam_limits.so): /lib/security/pam_limits.so: wrong ELF class: ELFCLASS32
    iRedMail退信问题的解决(转)
    curl NSS error -8179 (SEC_ERROR_UNKNOWN_ISSUER)
    看进程的启动时间长度 + vmstat + jstack 应用
    Nginx日志中的金矿
    php-fpm参数优化
    PHP扩展--opcache安装及配置
  • 原文地址:https://www.cnblogs.com/weitaoxiaozhu/p/6037928.html
Copyright © 2020-2023  润新知