将网页源下载到关键字

时间:2013-04-05 23:54:16

标签: python

我正在寻找从网站上下载特定关键字的源代码(这些网站都来自论坛,所以我只对第一篇帖子用户详细信息的源代码感兴趣)所以我只需要下载源代码,直到找到“<! - message,attachments,sig - >”这是源代码中的第一次。

How to get webpage title without downloading all the page source

这个问题虽然用不同的语言非常类似于我想要做的事情,虽然我不熟悉python,所以我无法弄清楚如何将这个答案重新编码为python。

1 个答案:

答案 0 :(得分:0)

首先,请注意,在取消之前,您可能已经将每个页面的全部或大部分内容放入了OS缓冲区,NIC,路由器或ISP,因此这样做可能没有任何好处。并且会有成本 - 如果您提前关闭它们,则无法重复使用连接;如果你想早点取消,你必须一次recv个小件;等

如果你对可能需要阅读的字节数有一个大概的了解(通常稍微好一些,有时候会略微下去),并且服务器处理HTTP范围请求,你可能想尝试一下而不是请求整个文件,然后提前关闭套接字。

但是,如果你想知道如何提前关闭套接字:

urllib2.urlopenrequests以及大多数其他高级库都围绕着您想要读取整个文件的想法而设计。它们在数据进入时缓冲数据,为您提供高级文件类接口。最重要的是,他们的API正在阻止。这两者都不是你想要的。您希望尽可能快地获取字节,当您关闭套接字时,您希望尽可能在recv之后尽快。

因此,您可能需要考虑使用libcurl周围的一个Python包装器,这样可以在功耗/灵活性和易用性之间取得相当好的平衡。例如,使用pycurl

import pycurl

buf = ''

def callback(newbuf):
    global buf
    buf += newbuf
    if '<div style="float: right; margin-left: 8px;">' in buf:
        return 0
    return len(newbuf)

c = pycurl.Curl()
c.setopt(c.URL, 'http://curl.haxx.se/dev/')
c.setopt(c.WRITEFUNCTION, callback)
try:
    c.perform()
except Exception as e:
    print(e)
c.close()

print len(buf)

事实证明,这最终会在该测试中读取12259/12259字节。但是,如果我将其更改为前2650字节中的字符串,我只读取2650/12259字节。如果我启动Wireshark和仪器recv,我可以看到,虽然下一个数据包确实到达我的NIC,但我从未真正读过它;我收到2650字节后立即关闭了套接字。所以,可能会节省一些时间......虽然可能不会太多。更重要的是,如果我把它扔到一个13MB的图像文件并尝试在1MB之后停止,我只会额外收到几KB,并且大部分图像还没有到达我的路由器(尽管它可能全部离开服务器,如果你完全关心对服务器的好感,那么肯定节省一些时间。

当然,典型的论坛页面更接近12KB而不是13MB。 (例如,即使在我所有的漫步之后,这个页面也远低于48KB。)但也许你正在处理非典型论坛。

如果页面非常大,您可能希望将代码更改为仅每次检查buf[-len(needle):] + newbuf而不是整个缓冲区。即使使用13MB的图像,一遍又一遍地搜索整个内容并没有增加总运行时间,但它 将我的CPU使用率从1%提高到9%......

最后一件事:如果你正在阅读500页,那么同时进行 - 比如说,每次8个 - 可能会比你早点取消每个页面节省更多的时间。两者结合起来可能比单独使用更好,所以这不是反对这样做的论据 - 这只是建议那个。 (如果您想让curl为您处理并发性,请参阅receiver-multi.py示例...或者只使用multiprocessingconcurrent.futures来使用子进程池。)