我正在编写一个爬虫,定期检查新文章的新闻网站列表。 我已经阅读了有关避免不必要的页面下载的不同方法,基本上确定了5个标题元素,可用于确定页面是否已更改:
优秀FeedParser.org似乎实施了其中一些方法。
我正在寻找用于做出这种决定的Python(或任何类似语言)的最佳代码。 请记住,标题信息始终由服务器提供。
这可能是这样的:
def shouldDonwload(url,prev_etag,prev_lastmod,prev_expires, prev_content_length):
#retrieve the headers, do the magic here and return the decision
return decision
答案 0 :(得分:2)
在提出请求之前,您唯一需要检查的是Expires
。 If-Modified-Since
不是服务器发送给您的东西,而是您发送服务器的东西。
您要做的是HTTP GET
,其中If-Modified-Since
标头指示您上次检索资源的时间。如果您返回状态代码304
而不是通常的200
,则此后资源尚未修改,您应该使用存储的副本(不会发送新副本)。
此外,您应该保留上次检索文档时的Expires
标题,如果您保存的文档副本尚未过期,则根本不会发出GET
。
将其转换为Python仍然是一个练习,但应该直接向请求添加If-Modified-Since
标头,从响应中存储Expires
标头,并检查状态代码来自回应。
答案 1 :(得分:1)
您需要将标题的dict传递给shouldDownload
(或urlopen
的结果):
def shouldDownload(url, headers, prev_etag, prev_lastmod, prev_expires, prev_content_length):
return (prev_content_length != headers.get("content-length") || prev_lastmod != headers.get("If-Modified-Since") || prev_expires != headers.get("Expires") || prev_etag != headers.get("ETAG"))
# or the optimistic way:
# return prev_content_length == headers.get("content-length") and prev_lastmod == headers.get("If-Modified-Since") and prev_expires = headers.get("Expires") and prev_etag = headers.get("ETAG")
打开网址时执行此操作:
# my urllib2 is a little fuzzy but I believe `urlopen()` doesn't
# read the whole file until `.read()` is called, and you can still
# get the headers with `.headers`. Worst case is you may have to
# `read(50)` or so to get them.
s = urllib2.urlopen(MYURL)
try:
if shouldDownload(s.headers):
source = s.read()
# do stuff with source
else:
continue
# except HTTPError, etc if you need to
finally:
s.close()