6

Python Requests モジュールを使用して Web サイトのデータマイニングを行っています。データマイニングの一環として、フォームを HTTP POST し、結果の URL をチェックして成功したかどうかを確認する必要があります。私の質問は、POST の後、サーバーにページ全体を送信しないように要求することは可能ですか? URL を確認するだけで済みますが、プログラムはページ全体をダウンロードし、不要な帯域幅を消費します。コードはとてもシンプルです

import requests
r = requests.post(URL, payload)
if 'keyword' in r.url:
   success
fail
4

3 に答える 3

2

実装可能であれば、簡単な解決策です。低レベルに行くことです。ソケットライブラリを使用します。たとえば、本文にデータを含むPOSTを送信する必要があります。これをクローラーで1つのサイトに使用しました。

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.
于 2013-03-02T20:43:35.977 に答える
0

リクエストしようとしているサンプルURLなど、さらにデータを提供すると便利です。そうは言っても、リダイレクトまたはHTTP 404エラーに依存する次のアルゴリズムを使用して、POSTリクエストの後に正しい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リクエスト(GET、POSTなどの別のタイプのHTTPリクエスト)を使用して、ページ本文ではなくヘッダーのみを取得することです。次に、応答コードとリダイレクト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!"

これがあなたが探しているものではない場合は、要件に関する追加の詳細が役立ちます。少なくとも、これにより、すべてのページデータを取得することなく、ステータスコードとヘッダーを取得できます。

于 2012-11-07T19:24:51.370 に答える
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に指定された URL で使用できます。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'}
于 2012-11-07T20:07:44.507 に答える