如果获得页面跳转的最终URL

最近做一个小功能,就是获取一个页面经过跳转后的最终页面URL,这里的跳转方式包含但不仅限于HTTP 301/302、js、meta refresh。下面是我想到的三种可能的解决方式,可能会有更优的方法,期望大家提出更好的方法。
1. 首先的解决方法就是解析html页面,获得html页面中跳转的URL。
这种方式是我能想到的最高效、速度最快的方法,但是也有可能是最难维护的,因为我们必须对各种跳转方式都要了解。现在我所遇到的是HTTP 302/301windows.location.hrefmeta http-equiv="refresh" content="0; url=http://www.nsfocus.com/",这仅仅是我当前遇到的,不用说还有更多的跳转方式,而且跳转的条件也有各种,所以要保证功能的可用性你得不断的维护解析代码。
这个方法还要注意的就是多级跳转的情况,代码就不上了,因为当时我也没决定用这种方法。
2. 用Selenium+Chrome(Firefox)借助浏览器一劳永逸的方法。
前面解析html页面的方法可能会遇到各种我们未知的跳转问题,我们何不站在”伟人”的肩膀上,借助她们的力量来帮我们解决这些棘手的问题。
Selenium是大家熟悉的自动化测试的开源软件,通过Selenium加载本地的浏览器,通过浏览器来做页面的加载跳转,获得最终的跳转URL。
因为程序运行的环境没有GUI所以得通过Xvfb来加载运行浏览器,PyVirtualDisplay是一个封装了Xvfb, Xephyr and Xvnc操作的工具包Python库。代码如下:

#!env python
#coding=utf-8
# 
# Author:       [email protected]
# 
# Created Time: 2016年07月31日 星期日 21时16分04秒
# 
# FileName:     redirect.py
# 
# Description:  
# 
# ChangeLog:

from pyvirtualdisplay import Display
from selenium import webdriver

display = Display(visible=0, size=(1024, 768))
display.start()

driver = webdriver.Chrome('/home/lxg/chromedriver')
driver.implicitly_wait(30)
link = "https://jf.bankofrizhao.com.cn/"
driver.get(link)

redirected_url = driver.current_url
print 30*'='
print redirected_url
print 30*'='
driver.close() # Close the current window.
driver.quit() # Quit the driver and close every associated window.
display.stop()

这种方法从效果来说比较好,我们无需关注页面的可能跳转方法有哪些,因为Chrome都会替我们解决。但是这种方式比前面的解析html页面的方法可能就是消耗的资源比较多、运行时间也会稍长。
3. 使用Headless browsers的PhantomJS。
PhantomJS是一个无界面的webkit内核浏览器,你可以把它当作一个没有界面的Safari。既然是一个浏览器那么它应该也能满足我们的需求,下面是我从网上copy回来的一段代码:

var sys = require('system');
var pageUrl = ( sys.args[1] ) ? sys.args[1] : phantom.exit(0);

function forceExit(){
    phantom.exit(0);
}

var renderPage = function (url) {
    var page = require('webpage').create();

    page.onNavigationRequested = function(url, type, willNavigate, main) {
        var tmpUrl = ( url.substr(url.length - 1) != '/' ) ? url+'/' : url;
        var tmpPageUrl = ( pageUrl.substr( pageUrl.length - 1) != '/' ) ? pageUrl+'/' : pageUrl;
        if (main && tmpUrl!=tmpPageUrl && url!='about:blank') {
            pageUrl = url;
            sys.stdout.write(url+'\n');
            setTimeout(forceExit,1000 );
        }
    };

    page.open(url, function(status) {
        if ( status != 'success' ) {
            phantom.exit( 1 );
        } else {
            phantom.exit( 0 );
        }
    },100);

    setTimeout(forceExit,2000 );
};

renderPage( pageUrl );

这段代码能够获取js跳转,但是对于meta refresh跳转却不支持,当然对于HTTP 302/301也不支持。大致浏览了一边API也没能找到完美的解决方法。
后面的两种方法相对来说比较”重”,因为我这次对于程序的运行效率不太在乎,所以我就选择了第二中方法。

你可能感兴趣的:(http)