使用Scrapy进行认证用户会话抓取
在Scrapy 文档中,有一个例子说明了如何在 Scrapy 中使用经过身份验证的会话:
class LoginSpider(BaseSpider):
name = 'example.com'
start_urls = ['http://www.example.com/users/login.php']
def parse(self, response):
return [FormRequest.from_response(response,
formdata={'username': 'john', 'password': 'secret'},
callback=self.after_login)]
def after_login(self, response):
# check login succeed before going on
if "authentication failed" in response.body:
self.log("Login failed", level=log.ERROR)
return
# continue scraping with authenticated session...
我已经把这个搞定了,没问题。但我想问的是:要如何才能继续使用经过身份验证的会话进行抓取
,正如最后一行的评论所说的那样?
1 个回答
74
在上面的代码中,FormRequest
用来进行登录认证,它设置了一个叫after_login
的函数作为回调。这意味着,当登录尝试完成后,after_login
函数会被调用,并且会传入登录后得到的页面。
接下来,它会检查你是否成功登录,方法是查看页面中是否包含特定的字符串,这里是"authentication failed"
。如果找到了这个字符串,说明登录失败,程序就结束了。
一旦程序走到这一步,它就知道你已经成功登录了,这时你可以开始发送新的请求或者抓取数据。所以在这个情况下:
from scrapy.selector import HtmlXPathSelector
from scrapy.http import Request
# ...
def after_login(self, response):
# check login succeed before going on
if "authentication failed" in response.body:
self.log("Login failed", level=log.ERROR)
return
# We've successfully authenticated, let's have some fun!
else:
return Request(url="http://www.example.com/tastypage/",
callback=self.parse_tastypage)
def parse_tastypage(self, response):
hxs = HtmlXPathSelector(response)
yum = hxs.select('//img')
# etc.
如果你查看 这里,你会看到一个在抓取之前先进行认证的爬虫示例。
在这个示例中,它在parse
函数中处理这些事情(这是任何请求的默认回调)。
def parse(self, response):
hxs = HtmlXPathSelector(response)
if hxs.select("//form[@id='UsernameLoginForm_LoginForm']"):
return self.login(response)
else:
return self.get_section_links(response)
所以,每当发起一个请求时,程序会检查响应中是否有登录表单。如果有,那就说明需要登录,于是调用相应的函数;如果没有,就调用负责从响应中抓取数据的函数。
希望这些解释清楚了,如果你还有其他问题,随时问我!
编辑:
好的,你想做的不仅仅是发起一个请求并抓取数据。你还想跟踪链接。
要做到这一点,你只需要从页面中抓取相关的链接,然后用这些网址发起请求。例如:
def parse_page(self, response):
""" Scrape useful stuff from page, and spawn new requests
"""
hxs = HtmlXPathSelector(response)
images = hxs.select('//img')
# .. do something with them
links = hxs.select('//a/@href')
# Yield a new request for each link we found
for link in links:
yield Request(url=link, callback=self.parse_page)
如你所见,它会为页面上的每个网址发起一个新的请求,而每个请求都会调用同样的函数来处理响应,这样就形成了一种递归抓取的方式。
我上面写的只是一个示例。如果你想要“爬取”页面,建议你查看 CrawlSpider
,而不是手动处理这些事情。