在类似爬虫的项目中,我们有一个共同且广泛使用的任务来解析/扩展数千个URL。假设我们有(非常简化的例子):
GET'http://bit.ly/4Agih5'请求返回3xx中的一个,我们按照重定向到右边:
GET'http://stackoverflow.com'返回200.所以'stackoverflow.com'是我们需要的结果。
允许任何URL(不仅仅是bit.ly等众所周知的缩写词)作为输入。其中一些重定向一次,一些不重定向(在这种情况下结果是URL本身),一些重定向多次。 我们的任务是尽可能地遵循所有重定向模仿浏览器行为。一般来说,如果我们有一些网址A
解析器应该返回我们的网址B
,它应该与如果在某个浏览器中打开了A
。
到目前为止,我们使用Java,线程池和简单URLConnection
来解决此任务。优势显而易见:
URLConnection
,设置跟随重定向即可(几乎); 不幸的是,这种方法也有缺点:
URLConnection
会在getInputStream()
之后立即开始下载文档,即使我们不需要它; URL
和URLConnection
是非常重的对象,并且在{{1}之后再次缓冲GET结果呼叫。是否有其他解决方案(或改进此解决方案)可能会显着提高速度并降低内存消耗?据推测,我们需要以下内容:
答案 0 :(得分:1)
我会使用selenium脚本从队列中读取网址并GET
。然后每个浏览器等待大约5秒钟以查看是否发生重定向,如果是,则将新的重定向URL重新放入队列以供下一个要处理的实例。您可以根据需要同时运行多个实例。
<强>更新强>:
如果您只关心Location标头(大多数非JS或元重定向使用的),只需检查它,您就不需要获取inputStream
:
HttpURLConnection.setFollowRedirects(false);
URL url = new URL("http://bit.ly/abc123");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
String newLocation = conn.getHeaderField("Location");
如果填充了newLocation
,那么请将该网址粘贴回队列,然后在下一轮进行。
答案 1 :(得分:1)
您可以使用Python,Gevent和urlopen。将this gevent exampel与the redirect handling in this SO question结合使用。
我不推荐Nutch,它设置起来非常复杂并且有很多依赖项(Hadoop,HDFS)。