网络爬虫如何获取重定向链

我们知道网页重定向有3种方式

1.http重定向
2.mata tag重定向
3.js重定向

如果用http client,可以搞定1和2,但是对于3是无能为力的。

要做到js重定向必须依赖浏览器。但是selenium chromedriver并没有直接提供获取重定向链的功能,可以通过performance log来获取。不幸的是chrome最新版已经对应w3c,但是selenium chromedriver的安定版还没有对应。这个功能要4.0版才有,目前只有4.0alpha04的版本,因为很着急,暂时用这个版本,目前还没有发现问题。

取到了log后,该如何分析,网上没有找到资料,经过艰苦的分析,得到下面代码片段,与大家分享

这段代码可以分析重定向链的url,重定向原因,状态码

            var redirectChain = new List();

            var logs = driver.Manage().Logs.GetLog("performance"); //all your logs with redirects will be here


            var redirectPage = new RedirectPage();

            RedirectPage redirectPage=null;
            string frameId = null;
            string requestId = null;
            foreach (LogEntry log in logs)
            {
                JObject msg = JObject.Parse(log.Message);
                switch ((string)msg["message"]["method"])
                {
                    case "Network.requestWillBeSent":
                        if (frameId == null || (string)msg["message"]["params"]["frameId"] == frameId && (string)msg["message"]["params"]["loaderId"] == (string)msg["message"]["params"]["requestId"])
                        {
                            if (frameId == null)
                            {
                                if ((string)msg["message"]["params"]["frameId"]== (string)msg["webview"])
                                {
                                    frameId = (string)msg["message"]["params"]["frameId"];
                                }
                                else
                                {
                                    break;
                                }
                            }
                            if (msg["message"]["params"]["redirectResponse"] !=null)
                            {
                                var result = redirectChain.Last();
                                if (result != null)
                                {
                                    result.reason = "Location";
                                    result.status = (int)msg["message"]["params"]["redirectResponse"]["status"];
                                    result.squidError = (string)msg["message"]["params"]["redirectResponse"]["headers"]["X-Squid-Error"];
                                }
                            }
                            redirectPage = new RedirectPage();
                            requestId = (string)msg["message"]["params"]["requestId"];
                            redirectPage.url = (string)msg["message"]["params"]["documentURL"];
                            redirectChain.Add(redirectPage);
                        }
                        break;
                    case "Network.responseReceived":
                        if (requestId == (string)msg["message"]["params"]["requestId"])
                        {
                            redirectPage.status = (int)msg["message"]["params"]["response"]["status"];
                            redirectPage.squidError = (string)msg["message"]["params"]["response"]["headers"]["X-Squid-Error"];
                        }
                        break;
                    case "Page.frameScheduledNavigation":
                        if( frameId == (string)msg["message"]["params"]["frameId"])
                        {
                            int lastIndex = redirectChain.Count-1;
                            if (lastIndex > 0 && redirectChain[lastIndex].url == (string)msg["message"]["params"]["url"])
                            {
                                redirectChain[lastIndex-1].reason = (string)msg["message"]["params"]["reason"];
                            }
                            else
                            {
                                redirectChain[lastIndex].reason = (string)msg["message"]["params"]["reason"];
                            }
                        }
                        break;
                }
            }

结果放到redirectChain 里面,RedirectPage的结构如下

    //重定向页面状态
    public class RedirectPage
    {
        public string url;
        public int status;
        public string squidError;
        public string reason;
    }

说实话这个代码很奇怪,特别是获取重定向原因的代码,最后只能这样写,没有其他办法。找到数据之间的关系花了不少时间,这个日志本来就不是为获取重定向链准备的。

你可能感兴趣的:(c#)