请求 - 获取内容类型/大小而不获取整个页面/内容

Posted

技术标签:

【中文标题】请求 - 获取内容类型/大小而不获取整个页面/内容【英文标题】:Requests - get content-type/size without fetching the whole page/content 【发布时间】:2014-07-06 06:32:50 【问题描述】:

我有一个简单的网站爬虫,它工作正常,但有时它会因为 ISO 映像、.exe 文件和其他大文件等大内容而卡住。使用文件扩展名猜测内容类型可能不是最好的主意。

是否可以在不获取整个内容/页面的情况下获取内容类型和内容长度/大小?

这是我的代码:

requests.adapters.DEFAULT_RETRIES = 2
url = url.decode('utf8', 'ignore')
urlData = urlparse.urlparse(url)
urlDomain = urlData.netloc
session = requests.Session()
customHeaders = 
if maxRedirects == None:
    session.max_redirects = self.maxRedirects
else:
    session.max_redirects = maxRedirects
self.currentUserAgent = self.userAgents[random.randrange(len(self.userAgents))]
customHeaders['User-agent'] = self.currentUserAgent
try:
    response = session.get(url, timeout=self.pageOpenTimeout, headers=customHeaders)
    currentUrl = response.url
    currentUrlData = urlparse.urlparse(currentUrl)
    currentUrlDomain = currentUrlData.netloc
    domainWWW = 'www.' + str(urlDomain)
    headers = response.headers
    contentType = str(headers['content-type'])
except:
    logging.basicConfig(level=logging.DEBUG, filename=self.exceptionsFile)
    logging.exception("Get page exception:")
    response = None

【问题讨论】:

不是存储在变量contentType中吗? 是的,它存储在 contentType 中,但内容已经获取。 啊我明白你的意思。看看我的回答。 【参考方案1】:

是的。

您可以使用Session.head 方法创建HEAD 请求:

response = session.head(url, timeout=self.pageOpenTimeout, headers=customHeaders)
contentType = response.headers['content-type']

HEAD 请求类似于 GET 请求,不同之处在于不会发送消息正文。

这是来自Wikipedia的引用:

头部 请求与对应于 GET 请求的响应相同的响应,但没有响应正文。这对于检索写入响应标头中的元信息很有用,而无需传输整个内容。

【讨论】:

既然 OP 也问过这个问题:资源的大小(以字节为单位)可以通过response.headers['content-length'] 访问。 @LukasGraf 啊,是的。谢谢。【参考方案2】:

为此使用requests.head()。它不会返回消息正文。如果您只对headers 感兴趣,则应使用head 方法。详情请查看this link。

h = requests.head(some_link)
header = h.headers
content_type = header.get('content-type')

【讨论】:

【参考方案3】:

对不起,我的错误,我应该更好地阅读文档。这是答案: http://docs.python-requests.org/en/latest/user/advanced/#advanced(正文内容工作流程)

tarball_url = 'https://github.com/kennethreitz/requests/tarball/master'
r = requests.get(tarball_url, stream=True)
if int(r.headers['content-length']) > TOO_LONG:
  r.connection.close()
  # log request too long

【讨论】:

那不也可以获取尸体吗?尝试获取r.text @aIKid 使用stream=True 它实际上还不会获取身体。标头将被接收,请求将在读取正文之前停止。关闭连接应该完全防止您加载身体。也就是说,这应该是使用 HEAD 的后备选项,因为并非所有服务器都能正确响应 HEAD 请求。 +1。带有.get()stream=True 设置优于.head()。某些服务器可能会拒绝 HEAD 请求并返回 405 错误。 amazon.com 就是一个这样的例子。【参考方案4】:

因为requests.head() 自动重定向,所以URL 会被重定向,requests.head() 将得到Content-Length 的0。所以请确保添加了allow_redirects=True

r = requests.head(url, allow_redirects=True)
length = r.headers['Content-Length']

参考Requests Redirection And History

【讨论】:

以上是关于请求 - 获取内容类型/大小而不获取整个页面/内容的主要内容,如果未能解决你的问题,请参考以下文章

js获取页面各种宽高

从内容而不是从扩展名中获取文件类型[重复]

父页面获取子页面的内容

使用 Selenium 获取整个页面的内容 [重复]

如何获取在webview中显示的html页面的整个内容文本

一爬虫之基础