0

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

如何在不下载所有页面源的情况下获取网页标题

这个问题虽然使用不同的语言,但与我想要做的事情非常相似,尽管我对 python 没有那么丰富的经验,所以我不知道如何将答案重新编码成 python。

4

1 回答 1

0

首先,请注意,在您取消之前,您可能已经将每个页面的全部或大部分放入您的操作系统缓冲区、NIC、路由器或 ISP,因此这样做可能根本没有任何好处。并且会产生成本——如果你提前关闭它们,你就不能重用它们;recv如果您想提早取消,您必须一次只取小件;等等

如果您对可能需要读取多少字节有一个粗略的了解(最好经常超过一点,而不是有时会下降一点),并且服务器处理 HTTP 范围请求,您可能想尝试一下,而不是请求整个文件,然后提前关闭套接字。

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

urllib2.urlopen,requests和大多数其他高级库都是围绕您想要读取整个文件的想法设计的。它们在数据进入时缓冲数据,为您提供高级文件式界面。最重要的是,他们的 API 是阻塞的。这两者都不是你想要的。您希望尽可能快地获取传入的字节,并且当您关闭套接字时,您希望尽可能快地获得它们recv

因此,您可能需要考虑使用 Python 包装器之一libcurl,它可以让您在功能/灵活性和易用性之间取得很好的平衡。例如,使用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 和 instrument recv,我可以看到,虽然下一个数据包确实到达了我的 NIC,但我从未真正阅读过它;我收到 2650 个字节后立即关闭了套接字。所以,这可能会节省一些时间……虽然可能不会太多。不过,更重要的是,如果我将它扔到一个 13MB 的图像文件并尝试在 1MB 之后停止,我只会收到几 KB 的额外,而且大部分图像甚至还没有到达我的路由器(尽管它可能已经全部离开服务器,如果你关心对服务器友好的话),这样肯定节省一些时间。

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

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

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

于 2013-04-06T01:33:01.477 回答