Perl在获取HTML页面时胜过Python?

时间:2012-01-06 20:56:46

标签: python html perl

我有一个获取html页面的Perl脚本。我尝试用Python重写它(Just Coz我正在尝试学习Python),我发现它真的很慢!

这是Perl中的测试脚本

#!/usr/bin/perl
use LWP::Simple;

$url = "http://majorgeeks.com/page.php?id=";

open(WEB,">>"."perldata.txt");

for ($column = 1 ; $column <= 20 ; $column ++)

{

    $temp = $url.$column;
    print "val = $temp\n\n";

    $response=get($temp)or die("[-] Failed!!\n");

    print WEB "$response\n\n";

}

这是Python中的等效代码

import urllib2

url = "http://majorgeeks.com/page.php?id="

f = open("pydata.txt", 'w')

for i in range(20):

   tempurl = url + str(i+1)
   print "Val : " + tempurl + "\n\n"

   #req = urllib2.Request(tempurl)
   res = urllib2.urlopen(tempurl)

   f.write(res.read())

f.close()

我发现的差异很大! Perl脚本在大约30秒内完成。 虽然Python脚本花了大约7分钟。 (420秒)!!

我正在使用Ubuntu 11.10,64bit,Core i7,在12MBPS连接上进行测试。我试了好几次,每次都得到相同的差异。

我在这里做错了吗?或者我需要做点什么?或者差异是否合理? (我希望不会)

非常感谢你的帮助。

更新3: 我刚刚回家并启动了我的笔记本电脑,再次运行代码,它在11秒内完成! :/是因为我“重新启动”我的comp? Here's Profiler输出

注意 - Perl仍然花了31秒同样的事情!! :/

更新2: 正如@Makoto Here's所建议的那样,我所做的分析器数据。这真的很慢!我知道一些python配置与此有关,但不知道是什么。对于一个简单的请求,它不应该花20秒!!!

更新: 固定url到tempurl。按照此处的建议注释掉urllib2.Request。没有多大区别。

3 个答案:

答案 0 :(得分:2)

您的代码可以改进,但我不确定它是否会解决所有性能问题:

from urllib2 import urlopen

url = "http://majorgeeks.com/page.php?id={}"

with open("pydata.txt", 'w') as f:
    for i in xrange(1, 21):
        tempurl = url.format(i)
        print "Val : {}\n\n".format(tempurl)
        f.write(urlopen(tempurl).read())

我也在逻辑上更改了它 - 它现在请求不同的URL(由tempurl定义),它用于请求相同的URL 20次(由url定义)。我也使用了字符串格式,虽然我不确定它如何影响效率。

我在我的系统上测试过它(Windows 7 64位,Python 2.7.2,IDLE内部,中等互联网连接),完成时需要40秒(40.262)。

答案 1 :(得分:1)

我仍然需要抓住我的头脑,弄清楚为什么这段代码对@mayjune和@Tadeck来说都花了这么长时间。我有机会通过分析器正式运行两段代码,结果如下。我强烈建议您在自己的机器上运行这些结果,因为我会产生不同的结果(AMD Athlon II X4 @ 3GHz,8GB RAM,Ubuntu 11.04 x64,7Mbit线)。

运行:

python -m cProfile -o profile.dat <path/to/code.py>; python -m pstats profile.dat

(从探查器内部,您可以检查help命令。)


原始代码:

Fri Jan  6 17:49:29 2012    profile.dat

20966 function calls (20665 primitive calls) in 13.566 CPU seconds

Ordered by: cumulative time
List reduced from 306 to 15 due to restriction <15>

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1    0.001    0.001   13.567   13.567 websiteretrieval.py:1(<module>)
20    0.000    0.000    7.874    0.394 /usr/lib/python2.7/urllib2.py:122(urlopen)
20    0.000    0.000    7.874    0.394 /usr/lib/python2.7/urllib2.py:373(open)
20    0.000    0.000    7.870    0.394 /usr/lib/python2.7/urllib2.py:401(_open)
40    0.000    0.000    7.870    0.197 /usr/lib/python2.7/urllib2.py:361(_call_chain)
20    0.000    0.000    7.870    0.393 /usr/lib/python2.7/urllib2.py:1184(http_open)
20    0.001    0.000    7.870    0.393 /usr/lib/python2.7/urllib2.py:1112(do_open)
1178    7.596    0.006    7.596    0.006 {method 'recv' of '_socket.socket' objects}
20    0.000    0.000    5.911    0.296 /usr/lib/python2.7/httplib.py:953(request)
20    0.000    0.000    5.911    0.296 /usr/lib/python2.7/httplib.py:974(_send_request)
20    0.000    0.000    5.911    0.296 /usr/lib/python2.7/httplib.py:938(endheaders)
20    0.000    0.000    5.911    0.296 /usr/lib/python2.7/httplib.py:796(_send_output)
20    0.000    0.000    5.910    0.296 /usr/lib/python2.7/httplib.py:769(send)
20    0.000    0.000    5.909    0.295 /usr/lib/python2.7/httplib.py:751(connect)
20    0.001    0.000    5.909    0.295 /usr/lib/python2.7/socket.py:537(create_connection)

......所以从观察来看,唯一可能让你失望的是...... urlopenopen。 I / O很慢,所以这是可以理解的。

修订代码

Fri Jan  6 17:52:36 2012    profileTadeck.dat

21008 function calls (20707 primitive calls) in 13.249 CPU seconds

Ordered by: cumulative time
List reduced from 305 to 15 due to restriction <15>

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
1    0.002    0.002   13.249   13.249 websiteretrievalTadeck.py:1(<module>)
20    0.000    0.000    7.706    0.385 /usr/lib/python2.7/urllib2.py:122(urlopen)
20    0.000    0.000    7.706    0.385 /usr/lib/python2.7/urllib2.py:373(open)
20    0.000    0.000    7.702    0.385 /usr/lib/python2.7/urllib2.py:401(_open)
40    0.000    0.000    7.702    0.193 /usr/lib/python2.7/urllib2.py:361(_call_chain)
20    0.000    0.000    7.702    0.385 /usr/lib/python2.7/urllib2.py:1184(http_open)
20    0.001    0.000    7.702    0.385 /usr/lib/python2.7/urllib2.py:1112(do_open)
1178    7.348    0.006    7.348    0.006 {method 'recv' of '_socket.socket' objects}
20    0.000    0.000    5.841    0.292 /usr/lib/python2.7/httplib.py:953(request)
20    0.000    0.000    5.841    0.292 /usr/lib/python2.7/httplib.py:974(_send_request)
20    0.000    0.000    5.840    0.292 /usr/lib/python2.7/httplib.py:938(endheaders)
20    0.000    0.000    5.840    0.292 /usr/lib/python2.7/httplib.py:796(_send_output)
20    0.000    0.000    5.840    0.292 /usr/lib/python2.7/httplib.py:769(send)
20    0.000    0.000    5.839    0.292 /usr/lib/python2.7/httplib.py:751(connect)
20    0.001    0.000    5.839    0.292 /usr/lib/python2.7/socket.py:537(create_connection)

同样,花费时间的最大两个罪魁祸首是urlopenopen。这让我相信I / O在破坏代码方面起着重要作用。但是,我测试它的机器上的差异并不大 - Perl的脚本大致在同一时间执行。

real    0m11.129s
user    0m0.230s
sys 0m0.070s

虽然你的机器非常强大,但我不相信你的代码很慢是软件的错。我强烈建议您运行探查器套件(上面包含代码),看看是否能找到我错过的任何瓶颈。

答案 2 :(得分:0)

我真的不知道,你为什么会得到这个奇怪的结果。但是让我建议真正快速的解决方案。使用一些异步库。我喜欢gevent,非常漂亮{​​{3}}

代码:

from requests import async
import time

begin = time.time()
url = "http://majorgeeks.com/page.php?id=%s"
rs = [async.get(url % i) for i in xrange(1, 21)]
responses = async.map(rs, size=10)

with open("pydata.txt", 'w') as f:
    for response in responses:
        print response.url
        f.write(response.content)

print 'Elapsed:', (time.time()-begin)

只需2.45秒。

修改

urllib2.urlopen的可能原因:

    系统环境中的
  • http_proxy

  • 网站以某种方式减慢urllib2代理,限制自动抓取