看到网上大都是豆瓣爬虫登录的示例,于是自己也搞了一个。

登录逻辑分析

跟网上看到的不太一样,网上基本上都是抓取页面,获取到登录页表单,检测时候有验证码,如果有则下载,没有则直接表单提交登录。而通过我自己对豆瓣登录页的分析,并没有看到页面包括表单元素,豆瓣的登录是通过Ajax提交的。

登录页地址:https://accounts.douban.com/passport/login

使用Ajax登录豆瓣

📃 登录逻辑处理 - 图1

既然找出了登录接口,那么要使用程序登录也不在话下了,我们先使用postman测试一下

📃 登录逻辑处理 - 图2

第一次发送请求,服务器返回参数错误,查看了下cookie,发现服务器种了一个cookie:

📃 登录逻辑处理 - 图3

再次发送请求,将会携带这个cookie,发现登录成功了:

📃 登录逻辑处理 - 图4

ok,到此,登录逻辑已经捋顺了,需要调用登录接口两次:第一次获取cookie,第二次携带cookie访问

登录接口如下:

  1. https://accounts.douban.com/j/mobile/login/basic

使用POST请求发送,携带以下头部信息:

  1. Content-Type: application/x-www-form-urlencoded
  2. Cookie: ...
  3. Accept: application/json
  4. User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36 Edg/81.0.416.68

传递以下几个参数:

  1. name 用户名
  2. password 密码
  3. remember 是否记住密码

登录前后页面分析

我们以豆瓣首页为例:https://www.douban.com/

在登录前访问豆瓣首页,看到页面长这样:

📃 登录逻辑处理 - 图5

有一个登录框,顶部有一行菜单:“读书”、“电影”等等

在登录后访问豆瓣首页,看到页面长这样:

📃 登录逻辑处理 - 图6

顶部菜单变为了“首页”、“我的豆瓣”等等,没有了输入框

我们点击“我的豆瓣”,可以看到豆瓣个人主页:

📃 登录逻辑处理 - 图7

在豆瓣主页中可以看到我们的昵称等信息。

我们退出登录,再次输入个人主页地址:https://www.douban.com/mine/,可以看到会被重定向到登录页面。

好的,所有逻辑都明了了,如果登录,我们跳转到个人主页,看下能不能获取到个人昵称,如果获取得到,说明登录成功了。

具体程序实现

spider程序如下:

  1. # -*- coding: utf-8 -*-
  2. import scrapy
  3. import json
  4. class LoginSpider(scrapy.Spider):
  5. name = 'login'
  6. url = 'https://accounts.douban.com/j/mobile/login/basic'
  7. data = {
  8. 'name': 'your name',
  9. 'password': 'your password',
  10. 'remember': "true"
  11. }
  12. def start_requests(self):
  13. # 第一次登录,由于缺少cookie,会返回登录错误,并设置cookie
  14. yield scrapy.FormRequest(
  15. url=self.url,
  16. formdata=self.data,
  17. method='POST',
  18. callback=self.getCookie
  19. )
  20. def getCookie(self, response):
  21. # scrapy会自动携带上一个请求设置的cookie
  22. yield scrapy.FormRequest(
  23. url=self.url,
  24. formdata=self.data,
  25. method='POST',
  26. callback=self.parse,
  27. # 添加以防止出现:Filtered duplicate request
  28. dont_filter=True
  29. )
  30. def parse(self, response):
  31. res = json.loads(response.body.decode())
  32. print("========")
  33. print(res)
  34. print("========")
  35. url = "https://www.douban.com/"
  36. yield scrapy.Request(url, callback=self.getHomePage)
  37. def getHomePage(self, response):
  38. navs = response.xpath("//div[@class='nav-items']//li")
  39. for nav in navs:
  40. title = nav.xpath(".//a/text()").extract_first().strip()
  41. url = nav.xpath(".//a/@href").extract_first()
  42. print(title.strip())
  43. print(url)
  44. if '我的豆瓣' in title:
  45. yield scrapy.Request(url, callback=self.getMyPage)
  46. def getMyPage(self, response):
  47. name = response.xpath("//div[@class='info']//h1/text()").extract_first().strip()
  48. print("====start: getMyPage====")
  49. print(name)
  50. print("====end: getMyPage====")

这里值得说明的是,第一次登录成功后,scrapy会保存获取到的cookie,在第二次访问登录接口的时候,会自动携带cookie访问。

第二次调用登录接口的时候,需要在请求中配置参数dont_filter=True,否则,Scrapy会认为此接口已经访问过了,不需要重新访问,返回一个Debug信息:Filtered duplicate request

登录成功后,获取顶部导航栏菜单,访问“我的豆瓣”,查看是否能够获取到昵称。

运行爬虫,看到控制台打印出以下数据(主要是要看到自己的昵称),说明登录成功了:
📃 登录逻辑处理 - 图8

注意需要在settings.py中进行以下配置:

  1. # Crawl responsibly by identifying yourself (and your website) on the user-agent
  2. USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
  3. # Obey robots.txt rules
  4. ROBOTSTXT_OBEY = False