登录、搜索这类表单怎么用 Scrapy 提交?from_response 会带哪些字段、点哪个按钮?disabled 字段呢?GET 和 POST 有什么不同?文件上传行不行?这篇在一个带各种控件的表单上逐项实测。
警告: ScrapyDeprecationWarning: FormRequest.from_response() is deprecated. Use the form2request library instead. FormRequest(url, formdata=…) 直接构造的警告数: 0
2.19 里 FormRequest.from_response() 被标记为弃用,建议用 form2request 库;FormRequest(url, formdata=…) 直接构造没有警告。
formid="login",formdata 填 user、pass
POST http://site.test/do/login?next=1
body: [('csrf', 'tok123'), ('remember', 'yes'), ('plan', 'pro'), ('lang', 'zh'), ('multi', 'a'), ('multi', 'b'), ('bio', 'hello\nworld'), ('locked', 'x'), ('act', 'Login'), ('user', 'alice'), ('pass', 'pw')]
Content-Type: application/x-www-form-urlencoded默认收集隐藏字段、文本框默认值、选中的 checkbox/radio/select、textarea,并点第一个提交按钮;没选中的 checkbox 不带,disabled 字段仍会带上。
(不指定)默认第一个 → POST http://site.test/do/login?next=1 formnumber=1 → GET http://site.test/dir/search?q=python formname="loginform" → POST http://site.test/do/login?next=1 formid="search" → GET http://site.test/dir/search?q=python formxpath="//form[@action='search']" → GET http://site.test/dir/search?q=python formcss="form#search" → GET http://site.test/dir/search?q=python formnumber=5:抛 IndexError Form number 5 not found in <200 http://site.test/dir/page.html> 页面里没有表单:抛 ValueError No <form> element found in <200 http://site.test/dir/page.html>
用 formid / formname / formnumber / formxpath / formcss 选表单,不指定取第一个。
默认(第一个提交按钮) → 按钮相关字段 [('act', 'Login')]
clickdata={"value": "Register"} → 按钮相关字段 [('act', 'Register')]
clickdata={"name": "btn"} → 按钮相关字段 [('btn', 'b1')]
clickdata={"nr": 0}(form.inputs 的第 0 个是隐藏字段 csrf) → 按钮相关字段 []
clickdata={"nr": 12}(第 13 个控件) → 按钮相关字段 [('act', 'Register')]
clickdata={"value": "Nope"}(没有匹配) → 抛 ValueError: No clickable element matching clickdata: {'value': 'Nope'}
dont_click=True → 按钮相关字段 []clickdata 选按钮(nr 按 form.inputs 序号,不是第几个按钮),dont_click 不点。
formdata={remember: None, plan: enterprise, extra: [x, y], user: 中文}
POST http://site.test/do/login?next=1
body: [('csrf', 'tok123'), ('pass', ''), ('lang', 'zh'), ('multi', 'a'), ('multi', 'b'), ('bio', 'hello\nworld'), ('locked', 'x'), ('plan', 'enterprise'), ('extra', 'x'), ('extra', 'y'), ('user', '中文')]
Content-Type: application/x-www-form-urlencoded覆盖、追加、用 None 删除字段;列表产生多个同名参数。
POST 表单 action=/do/login?next=1
POST http://site.test/do/login?next=1
body: [('csrf', 'tok123'), ('user', ''), ('pass', ''), ('remember', 'yes'), ('plan', 'pro'), ('lang', 'zh'), ('multi', 'a'), ('multi', 'b'), ('bio', 'hello\nworld'), ('locked', 'x')]
Content-Type: application/x-www-form-urlencoded
GET 表单 action=search(相对路径)
GET http://site.test/dir/search?q=python
Content-Type: None
GET 表单,参数 method="POST" 覆盖
POST http://site.test/dir/search
body: [('q', 'python')]
Content-Type: application/x-www-form-urlencoded
<base href> 下的相对 action
GET http://other.test/base/x?a=1
Content-Type: None
表单没有 action
GET http://site.test/here?a=1
Content-Type: None
FormRequest(url, formdata={…}) 直接构造(值都是字符串)
POST http://site.test/post
body: [('k', 'v'), ('n', '1'), ('list', 'a'), ('list', 'b')]
Content-Type: application/x-www-form-urlencoded
formdata 里放整数 1:抛 TypeError to_bytes must receive a str or bytes object, got int
FormRequest(url, formdata=…, method="GET")
GET http://site.test/get?k=v
Content-Type: None相对 action 按页面 URL 或 <base> 补全;GET 表单把字段放进查询串;可用 method 参数覆盖。
enctype="multipart/form-data" 的表单
POST http://site.test/up
body: [('title', 't'), ('f', '')]
Content-Type: application/x-www-form-urlencoded
type=file 的字段是否出现在请求体里: True表单 enctype 被忽略,总是 urlencoded;文件字段只会变成空值参数。