我正在使用Python Requests Module对网站进行数据处理。作为数据挖掘的一部分,我必须通过HTTP POST表单并通过检查生成的URL来检查它是否成功。我的问题是,在POST之后,是否可以请求服务器不发送整个页面?我只需要检查URL,但我的程序会下载整个页面并消耗不必要的带宽。代码非常简单
import requests
r = requests.post(URL, payload)
if 'keyword' in r.url:
success
fail
答案 0 :(得分:2)
一个简单的解决方案,如果它可以实现。是低级别的。使用套接字库。 例如,您需要在其正文中发送包含一些数据的POST。我在我的Crawler中将它用于一个站点。
import socket
from urllib import quote # POST body is escaped. use quote
req_header = "POST /{0} HTTP/1.1\r\nHost: www.yourtarget.com\r\nUser-Agent: For the lulz..\r\nContent-Type: application/x-www-form-urlencoded; charset=UTF-8\r\nContent-Length: {1}"
req_body = quote("data1=yourtestdata&data2=foo&data3=bar=")
req_url = "test.php"
header = req_header.format(req_url,str(len(req_body))) #plug in req_url as {0}
#and length of req_body as Content-length
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) #create a socket
s.connect(("www.yourtarget.com",80)) #connect it
s.send(header+"\r\n\r\n"+body+"\r\n\r\n") # send header+ two times CR_LF + body + 2 times CR_LF to complete the request
page = ""
while True:
buf = s.recv(1024) #receive first 1024 bytes(in UTF-8 chars), this should be enought to receive the header in one try
if not buf:
break
if "\r\n\r\n" in page: # if we received the whole header(ending with 2x CRLF) break
break
page+=buf
s.close() # close the socket here. which should close the TCP connection even if data is still flowing in
# this should leave you with a header where you should find a 302 redirected and then your target URL in "Location:" header statement.
答案 1 :(得分:0)
如果您提供更多数据(例如,您尝试请求的示例网址),这将有所帮助。话虽这么说,在我看来,通常你在POST请求后使用以下算法依赖于重定向或HTTP 404错误来检查你是否有正确的URL:
if original_url == returned request url:
correct url to a correctly made request
else:
wrong url and a wrongly made request
如果是这种情况,你可以在这里做的是在Python的requests
库中使用HTTP HEAD请求(另一种类型的HTTP请求,如GET,POST等)来获取标题,而不是页面正文。然后,您将检查响应代码和重定向URL(如果存在)以查看您是否向有效URL发出请求。
例如:
def attempt_url(url):
'''Checks the url to see if it is valid, or returns a redirect or error.
Returns True if valid, False otherwise.'''
r = requests.head(url)
if r.status_code == 200:
return True
elif r.status_code in (301, 302):
if r.headers['location'] == url:
return True
else:
return False
elif r.status_code == 404:
return False
else:
raise Exception, "A status code we haven't prepared for has arisen!"
如果这不是您想要的,那么您的要求的其他详细信息将有所帮助。至少,它可以获取状态代码和标题,而不会提取所有页面数据。
答案 2 :(得分:0)
该网站有可能使用Post/Redirect/Get (PRG)模式。如果是这样,那么就足以不遵循重定向并从响应中读取Location
标题。
实施例
>>> import requests
>>> response = requests.get('http://httpbin.org/redirect/1', allow_redirects=False)
>>> response.status_code
302
>>> response.headers['location']
'http://httpbin.org/get'
如果您需要有关如果您遵循重定向会得到什么的更多信息,那么您可以在HEAD
标题中提供的网址上使用Location
。
实施例
>>> import requests
>>> response = requests.get('http://httpbin.org/redirect/1', allow_redirects=False)
>>> response.status_code
302
>>> response.headers['location']
'http://httpbin.org/get'
>>> response2 = requests.head(response.headers['location'])
>>> response2.status_code
200
>>> response2.headers
{'date': 'Wed, 07 Nov 2012 20:04:16 GMT', 'content-length': '352', 'content-type':
'application/json', 'connection': 'keep-alive', 'server': 'gunicorn/0.13.4'}