请求 - 在发出请求之前确定参数化URL,以包含在Referer头中

时间:2014-12-21 05:06:16

标签: python python-requests http-referer referer

我正在编写一个Python 2.7脚本,使用Requests自动访问特定网站。出于“安全原因”,网站要求提供与请求URL 匹配的Referer标头。该URL由params dict中的许多项构成,传递给requests.post()。

在发出请求之前,有没有办法确定请求将使用的URL是什么,以便可以将Referer标头设置为此正确值?我们假设我有很多参数:

params = { 'param1' : value1, 'param2' : value2, # ... etc
  }

base_url = "http://example.com"
headers = { 'Referer' : url }   # but what is 'url' to be?
requests.post(base_url, params=params, headers=headers)  # fails as Referer does not match final url

我想一个解决方法是在事后发出请求并查看URL是什么。但是这有两个问题 - 1.它会给脚本的执行时间增加很多开销,因为会有很多这样的请求,而且它实际上并不是一个有用的解决方法,因为服务器实际上将请求重定向到另一个URL,因此之后阅读它不会给出正确的Referer值。

我想请注意,我有这个脚本使用urllib / urllib2,我试图用Requests写它,看它是否可能,也许更简单。这不是一个脚本必须遵循的复杂过程,但它可能略微超出了请求的范围。那很好,我只想确认是这种情况。

2 个答案:

答案 0 :(得分:2)

我想我找到了一个基于Prepared Requests的解决方案。概念是Session.prepare_request()将执行所有操作以准备请求,除非发送它,这允许我的脚本然后读取准备好的请求的url,其现在包括其顺序由dict顺序确定的参数。然后它可以适当地设置Referer头,然后发出原始请求。

params = {'param1' : value1, 'param2' : value2, # ... etc
         }
url = "http://example.com"

# Referer must be correct
# To determine correct Referer url, prepare a request without actually sending it
req = requests.Request('POST', url, params=params)
prepped = session.prepare_request(req)
#r = session.send(prepped)   # don't actually send it

# add the Referer header by examining the prepared url
headers = { 'Referer': prepped.url }

# now send normally
r = session.post(url, params=params, data=data, headers=headers)

答案 1 :(得分:0)

您似乎已在“请求”中正确找到了prepare_request功能。

但是,如果你仍想使用初始方法,我相信你可以使用你的base_url作为你的Referer:

base_url = "http://example.com"
headers = { 'Referer' : base_url }
requests.post(base_url, params=params, headers=headers)

我怀疑这是因为您的POST将PARAMS直接附加到base_url。例如,如果你在:

http://www.example.com/trying-to-send-upload/

在此POST中添加一些参数,然后使用:

referer = "http://www.example.com/trying-to-send-something/"
headers = { 'Referer' : referer, 'Host' : 'example.com' }
requests.post(referer, params=params, headers=headers)

<强> ADDED

在您创建了URL字符串后,我会使用简单的语句直观地检查我的网址:

print(post_url)

如果这样做很好,您应该打印出您要发布到的服务器的回复详情,因为它也可能会为您提供一些关于您的查询被拒绝的提示:

s = requests.post(referer, params=params, headers=headers)
print(s.status_code)
print(s.text)

很高兴听到这对您有效。