1、scrapy模拟登录

为什么需要模拟登录?
获取cookie,能够爬取登录后的页面

回顾:
request是如何模拟登录的?

  • 1 直接携带cookies请求页面
  • 2 找接口发送post请求存储cookie

selenium是如何模拟登录的?

  • 找到对应的input标签,输入文字点击登录

那么对于scrapy来说,也是有两个方法模拟登录:

  • 1 直接携带cookie,需要重写start_requests方法(定义cookie的值),然后发送请求yield scrapy.Request(url=, cookies= ,callback=);headers中添加cookie的无法生效;
  • 2 找到发送post请求的URL地址,带上信息,发送请求

2、登录人人网

直接携带cookie登陆

  1. import scrapy
  2. class RrSpider(scrapy.Spider):
  3. name = 'rr'
  4. allowed_domains = ['renren.com']
  5. start_urls = ['http://www.renren.com/974376660/profile']
  6. def start_requests(self):
  7. url = self.start_urls[0]
  8. cookie_str = 'anonymid=k5819yjj-v87pet; _r01_=1; taihe_bi_sdk_uid=b2d2177e744b29a034cf8c5106c8d219; ln_uact=13415662175; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; _de=C4463AE8B4546175118A454C43DCC81C; depovince=ZGQT; jebecookies=6dfb56c2-aa43-4175-8b97-1fd4e3bf780a|||||; taihe_bi_sdk_session=cc2cc891cf727d3774964b40b9ec51d3; ick_login=9113ac97-37ac-4032-a411-a8a63fa7f725; p=939f755d6bc277295658b9e680c366c60; first_login_flag=1; t=0dae2e967bf60a114fe6382b71e9dd540; societyguester=0dae2e967bf60a114fe6382b71e9dd540; id=974376660; xnsid=caf49547; ver=7.0; loginfrom=null; wp_fold=0; wpsid=15830122379353'
  9. # headers = {
  10. # "Cookie": cookie_str
  11. # }
  12. cookies = {i.split("=")[0]: i.split("=")[1] for i in cookie_str.split("; ")}
  13. yield scrapy.Request(
  14. url=url,
  15. # headers=headers,
  16. callback=self.parse,
  17. cookies=cookies
  18. )
  19. def parse(self, response):
  20. print(response.body.decode())
  21. with open('人人.html', 'w', encoding='utf-8') as f:
  22. f.write(response.body.decode())

3、scrapy模拟登陆之发送post请求

3.1 如何发送?

使用yield scrapy.FormRequest(url= , formdata= , callback= )来方式post请求

  • url:表单要提交的地址;
  • formdata:要提交的表单数据;
  • callback:回调函数,表单提交完成后,要执行的方法;

3.2 formdata中含有可变参数时,如何寻找出其变化的规律?

  • 在网页源代码中查找是否有无该参数的value,有则可以通过请求url,xpath获取该参数的值;
  • 不在页面源代码中,看是否有无规律,比如+1之类的,或者看来源页中有无响应的参数值(一般列表页跳转到详情页时,列表页中往往含有跳转详情页所需的参数);
  • 在js中寻找,需要非常熟悉js代码,有相应的搜索经验(暂时还不会
  • 注意:formdata中有些参数哪怕是变化的,但其实不添加该参数,对表单的提交并不影响,比如时间戳、github中的ga_id(别的参数在页面中都有value,唯独它没有,所以可以尝试去掉)

    3.3 登录GitHub

    这里有一个坑就是,使用接口来第一次登入时,会重定向到填写一个验证码的地址,当有验证码时需要另外提交验证码的表单,这里要找出验证码提交的接口,以及提交的表单数据,来重新构造post请求;

找重定向验证码接口方法:
方法1将重定向后的响应保存为本地的html文件,在本地打开,随便输入一个验证码,找到该请求提交的地址以及参数;需要注意的是,因为打开的是一个本地的html文件,所以域名是localhost,需要将localhost改成github.com,这样才是验证表单要提交的地址;

方法2使用selenium去自动登入,一般请求接口需要验证码,selenium登入也会需要验证码,当重定向到验证码的页面时,同样随便输入一个验证码,找到该请求提交的地址以及参数;

  1. import scrapy
  2. class GithubSpider(scrapy.Spider):
  3. name = 'github'
  4. allowed_domains = ['github.com']
  5. start_urls = ['https://github.com/login']
  6. def parse(self, response):
  7. print('try login...')
  8. authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
  9. timestamp = response.xpath("//input[@name='timestamp']/@value").extract_first()
  10. timestamp_secret = response.xpath("//input[@name='timestamp_secret']/@value").extract_first()
  11. formdata = {
  12. "commit": "Sign in",
  13. "authenticity_token": authenticity_token,
  14. # "ga_id": "9383650.1568103844",
  15. "login": "",
  16. "password": "",
  17. "webauthn-support": "supported",
  18. "webauthn-iuvpaa-support": "unsupported",
  19. "timestamp": timestamp,
  20. "timestamp_secret": timestamp_secret
  21. }
  22. yield scrapy.FormRequest(
  23. url='https://github.com/session',
  24. callback=self.after_login,
  25. formdata=formdata
  26. )
  27. def after_login(self, response):
  28. print(response.url)
  29. if response.url == "https://github.com/sessions/verified-device":
  30. verified_url = "https://github.com/sessions/verified-device"
  31. authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
  32. otp = input("please input your verified_code: ")
  33. print(otp, authenticity_token)
  34. formdata = {
  35. "authenticity_token": authenticity_token,
  36. "otp": otp
  37. }
  38. yield scrapy.FormRequest(
  39. url=verified_url,
  40. formdata=formdata,
  41. callback=self.after_login
  42. )
  43. with open('github.html', 'w', encoding='utf-8') as f:
  44. f.write(response.text)
  45. if response.url == 'https://github.com/':
  46. print('login successful!')

4 scrapy模拟登陆之自动登录

Scrapy 对于表单请求,FormRequest 还提供了另外一个方法 from_response自动获取页面中的表单,我们只需要传入用户名和密码就可以发送请求。

4.1 如何发送?

使用yield scrapy.FormRequest.from_response(response= , formdata= , callback= )来方式post请求

  • response:登入页面的响应;
  • formdata:要提交的表单数据,这里只需要提交用户名和密码,因为其他参数的值,可以直接从页面的表单中获取;
  • callback:回调函数,表单提交完成后,要执行的方法; ```python import scrapy

class Github2Spider(scrapy.Spider): name = ‘github2’ allowed_domains = [‘github.com’] start_urls = [‘https://github.com/login‘]

  1. def parse(self, response):
  2. authenticity_token = response.xpath("//input[@name='authenticity_token']/@value").extract_first()
  3. timestamp = response.xpath("//input[@name='timestamp']/@value").extract_first()
  4. timestamp_secret = response.xpath("//input[@name='timestamp_secret']/@value").extract_first()
  5. formdata = {
  6. "login": "xiaobink96",
  7. "password": ""
  8. }
  9. yield scrapy.FormRequest.from_response(
  10. response=response,
  11. callback=self.after_login,
  12. formdata=formdata
  13. )
  14. def after_login(self, response):
  15. print(response.url)
  16. with open('github2.html', 'w', encoding='utf-8') as f:
  17. f.write(response.text)

```