mirror of https://github.com/scrapy/scrapy.git
Added formname parameter for FormRequest.from_response
This commit is contained in:
parent
400c4134af
commit
9288f622f9
|
|
@ -254,7 +254,7 @@ objects.
|
|||
The :class:`FormRequest` objects support the following class method in
|
||||
addition to the standard :class:`Request` methods:
|
||||
|
||||
.. classmethod:: FormRequest.from_response(response, [formnumber=0, formdata=None, clickdata=None, dont_click=False, ...])
|
||||
.. classmethod:: FormRequest.from_response(response, [formname=None, formnumber=0, formdata=None, clickdata=None, dont_click=False, ...])
|
||||
|
||||
Returns a new :class:`FormRequest` object with its form field values
|
||||
pre-populated with those found in the HTML ``<form>`` element contained
|
||||
|
|
@ -277,6 +277,11 @@ objects.
|
|||
to pre-populate the form fields
|
||||
:type response: :class:`Response` object
|
||||
|
||||
:param formname: if given, the form with name attribute set to this value
|
||||
will be used. Otherwise, ``formnumber`` will be used for selecting
|
||||
the form.
|
||||
:type formname: string
|
||||
|
||||
:param formnumber: the number of form to use, when the response contains
|
||||
multiple forms. The first one (and also the default) is ``0``.
|
||||
:type formnumber: integer
|
||||
|
|
@ -298,6 +303,9 @@ objects.
|
|||
The other parameters of this class method are passed directly to the
|
||||
:class:`FormRequest` constructor.
|
||||
|
||||
.. versionadded:: 0.10.3
|
||||
The ``formname`` parameter.
|
||||
|
||||
Request usage examples
|
||||
----------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -37,17 +37,27 @@ class FormRequest(Request):
|
|||
self.headers['Content-Type'] = 'application/x-www-form-urlencoded'
|
||||
|
||||
@classmethod
|
||||
def from_response(cls, response, formnumber=0, formdata=None,
|
||||
def from_response(cls, response, formname=None, formnumber=0, formdata=None,
|
||||
clickdata=None, dont_click=False, **kwargs):
|
||||
encoding = getattr(response, 'encoding', 'utf-8')
|
||||
forms = ParseFile(StringIO(response.body), response.url,
|
||||
encoding=encoding, backwards_compat=False)
|
||||
if not forms:
|
||||
raise ValueError("No <form> element found in %s" % response)
|
||||
try:
|
||||
form = forms[formnumber]
|
||||
except IndexError:
|
||||
raise IndexError("Form number %d not found in %s" % (formnumber, response))
|
||||
|
||||
form = None
|
||||
|
||||
if formname:
|
||||
for f in forms:
|
||||
if f.name == formname:
|
||||
form = f
|
||||
break
|
||||
|
||||
if not form:
|
||||
try:
|
||||
form = forms[formnumber]
|
||||
except IndexError:
|
||||
raise IndexError("Form number %d not found in %s" % (formnumber, response))
|
||||
if formdata:
|
||||
# remove all existing fields with the same name before, so that
|
||||
# formdata fields properly can properly override existing ones,
|
||||
|
|
|
|||
|
|
@ -330,6 +330,67 @@ class FormRequestTest(RequestTest):
|
|||
response = Response("http://www.example.com/lala.html", body=respbody)
|
||||
self.assertRaises(IndexError, self.request_class.from_response, response, formnumber=1)
|
||||
|
||||
def test_from_response_noformname(self):
|
||||
respbody = """
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="one" value="1">
|
||||
<input type="hidden" name="two" value="2">
|
||||
</form>
|
||||
"""
|
||||
response = Response("http://www.example.com/formname.html", body=respbody)
|
||||
r1 = self.request_class.from_response(response, formdata={'two':'3'}, callback=lambda x: x)
|
||||
self.assertEqual(r1.method, 'POST')
|
||||
self.assertEqual(r1.headers['Content-type'], 'application/x-www-form-urlencoded')
|
||||
fs = cgi.FieldStorage(StringIO(r1.body), r1.headers, environ={"REQUEST_METHOD": "POST"})
|
||||
self.assertEqual(fs['one'].value, '1')
|
||||
self.assertEqual(fs['two'].value, '3')
|
||||
|
||||
|
||||
def test_from_response_formname_exists(self):
|
||||
respbody = """
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="one" value="1">
|
||||
<input type="hidden" name="two" value="2">
|
||||
</form>
|
||||
<form name="form2" action="post.php" method="POST">
|
||||
<input type="hidden" name="three" value="3">
|
||||
<input type="hidden" name="four" value="4">
|
||||
</form>
|
||||
"""
|
||||
response = Response("http://www.example.com/formname.html", body=respbody)
|
||||
r1 = self.request_class.from_response(response, formname="form2", callback=lambda x: x)
|
||||
self.assertEqual(r1.method, 'POST')
|
||||
fs = cgi.FieldStorage(StringIO(r1.body), r1.headers, environ={"REQUEST_METHOD": "POST"})
|
||||
self.assertEqual(fs['three'].value, "3")
|
||||
self.assertEqual(fs['four'].value, "4")
|
||||
|
||||
def test_from_response_formname_notexist(self):
|
||||
respbody = """
|
||||
<form name="form1" action="post.php" method="POST">
|
||||
<input type="hidden" name="one" value="1">
|
||||
</form>
|
||||
<form name="form2" action="post.php" method="POST">
|
||||
<input type="hidden" name="two" value="2">
|
||||
</form>
|
||||
"""
|
||||
response = Response("http://www.example.com/formname.html", body=respbody)
|
||||
r1 = self.request_class.from_response(response, formname="form3", callback=lambda x: x)
|
||||
self.assertEqual(r1.method, 'POST')
|
||||
fs = cgi.FieldStorage(StringIO(r1.body), r1.headers, environ={"REQUEST_METHOD": "POST"})
|
||||
self.assertEqual(fs['one'].value, "1")
|
||||
|
||||
def test_from_response_formname_errors_formnumber(self):
|
||||
respbody = """
|
||||
<form name="form1" action="post.php" method="POST">
|
||||
<input type="hidden" name="one" value="1">
|
||||
</form>
|
||||
<form name="form2" action="post.php" method="POST">
|
||||
<input type="hidden" name="two" value="2">
|
||||
</form>
|
||||
"""
|
||||
response = Response("http://www.example.com/formname.html", body=respbody)
|
||||
self.assertRaises(IndexError, self.request_class.from_response, response, formname="form3", formnumber=2)
|
||||
|
||||
|
||||
class XmlRpcRequestTest(RequestTest):
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue