处理表单和基于表单的授权
在抓取网站内容之前,我们通常需要先登录网站。这通常是通过一个表单完成的,我们在表单中输入用户名和密码,按下回车键,然后就可以访问之前隐藏的内容了。这种表单验证通常被称为 cookie 授权,因为当我们授权时,服务器会创建一个 cookie,用来验证您是否已经登录。Scrapy 尊重这些 cookie,所以我们需要做的就是在抓取过程中以某种方式自动生成表单。
准备工作
我们将抓取容器网站中的一个页面,网址如下:http://localhost:5001/home/secured。在该页面以及来自该页面的链接中,有我们想要抓取的内容。但是,该页面被登录拦截。在浏览器中打开该页面时,我们会看到下面的登录表单,我们可以在其中输入用户名 darkhelmet 和密码 vespa:

按 Enter 键后,我们将通过身份验证并进入我们最初想要的页面。
那里的内容不多,但该消息足以验证我们是否已登录,并且我们的抓取工具也知道这一点。
如何做
我们按如下方式继续示例:
-
如果您检查登录页面的 HTML,您会注意到以下表单代码:
<form action="/Account/Login" method="post"> <div> <label for="Username">Username</label> <input type="text" id="Username" name="Username" value="" /> <span class="field-validation-valid" data-valmsg-for="Username" data-valmsg-replace="true"></span> </div> <div> <label for="Password">Password</label> <input type="password" id="Password" name="Password" /> <span class="field-validation-valid" data-valmsg-for="Password" data-valmsg-replace="true"></span> </div> <input type="hidden" name="returnUrl" /> <input name="submit" type="submit" value="Login"/> <input name="__RequestVerificationToken" type="hidden" value="CfDJ8CqzjGWzUMJKkKCmxuBIgZf3UkeXZnVKBwRV_Wu4qUkprH8b_2jno5-1 SGSNjFqlFgLie84xI2ZBkhHDzwgUXpz6bbBwER0v_- fP5iTITiZi2VfyXzLD_beXUp5cgjCS5AtkIayWThJSI36InzBqj2A" /> </form>
-
为了让 Scrapy 中的表单处理器正常工作,我们需要此表单中的用户名和密码字段的 ID。 它们分别是用户名和密码。 现在我们可以使用这些信息创建一个蜘蛛。 该蜘蛛位于脚本文件 06/09_forms_auth.py 中。 蜘蛛定义以以下内容开头:
class Spider(scrapy.Spider): name = 'spider' start_urls = ['http://localhost:5001/home/secured'] login_user = 'darkhelmet' login_pass = 'vespa'
-
我们在类中定义两个字段,login_user 和 login_pass,来保存我们要使用的用户名。爬虫也将从指定的 URL 开始。
-
然后更改解析方法以检查页面是否包含登录表单。 这是通过使用 XPath 查看是否存在密码类型且 id 为密码的输入表单来完成的:
def parse(self, response): print("Parsing: ", response) count_of_password_fields = int(float(response.xpath("count(//*/input[@type='password' and @id='Password'])").extract()[0])) if count_of_password_fields > 0: print("Got a password page")
-
如果找到该字段,我们将使用其 from_response 方法生成的 FormRequest 返回到 Scrapy:
return scrapy.FormRequest.from_response( response, formdata={'Username': self.login_user, 'Password': self.login_pass}, callback=self.after_login)
-
该函数传递响应,然后传递一个字典,该字典指定需要与这些值一起插入的数据的字段的 ID。 然后定义一个回调,在 Scrapy 执行此 FormRequest 后执行,并将结果表单的内容传递给该回调:
def after_login(self, response): if "This page is secured" in str(response.body): print("You have logged in ok!")
-
此回调仅查找 “This page is secure” 字样,仅在登录成功时才返回。 成功运行后,我们将从抓取器的打印语句中看到以下输出:
Parsing: <200 http://localhost:5001/account/login?ReturnUrl=%2Fhome%2Fsecured> Got a password page You have logged in ok!