菜鸟写Python实战:Scrapy完成知乎登录并保存cookies文件用于请求他页面(by Selenium)

xiaoxiao2021-03-01  16

一、前言

现在知乎的登录请求越来越复杂了,通过f12调出浏览器网络请求情况分析request参数,似乎不再简单可知了,因为知乎很多请求参数都字符加密显示了,如下图,我们很难再知道发起请求时要传递什么参数给它。

那这样,我们要怎么才能登录知乎,于似乎Selenium这个神器就出现了,它可以很方便的实现登录,详细的使用方法请参见:菜鸟写Python-Selenium操作:Selenium登录豆瓣并获取cookies

二、思路

我们知道知乎一些内容是需要登录才能看到,因此在爬取时的时候要先实现login,并把登录后的Cookies保存下来,爬取其他页面时将登录后的cookies一起传递过去,就可以已登录状态请求其他页面,所以核心在于如何保存cookie和加载保存的cookies的方式来记录用户的身份信息。

2.1 利用selenium模拟浏览器登录,非常简单和方便;

2.2 成功登录后,将登录的cookies保存成文件(此处通过json保存)-------------第一步的关键步骤;

2.3 之后请求其他页面时打开保存cookies的json文件,并获取文件中的name和value值,构建cookies的字典dict;

2.4 发起请求时,带上cookies=之间取出的dict类型的cookies。

通过上面的过程,我们就可以实现先通过login,记录cookies,然后在访问请求时带上记录的cookies访问即可。

三、代码实现

环境:win10+py3.6

工具:Pycharm

关键依赖库:Scrapy+selenium + json +time

通过scrapy构造spider的过程默认熟知,如有疑问可以微信添加:第一行Python代码;

详细代码和注释:

# -*- coding: utf-8 -*- # 导入依赖包 import scrapy from selenium import webdriver import time import json # 构建spider自动生成的基本配置 class ZhihuSpider(scrapy.Spider): name = 'zhihu' allowed_domains = ['www.zhihu.com'] start_urls = ['http://www.zhihu.com/'] # 模拟请求的headers,非常重要,不设置也可能知乎不让你访问请求 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0", "HOST": "www.zhihu.com" } # 第一步:使用selenium登录知乎并获取登录后的cookies,cookies没失效时,只要初次请求执行一次 def loginZhihu(self): # 登录网址 loginurl='https://www.zhihu.com/signin' # 加载webdriver驱动,用于获取登录页面标签属性 driver=webdriver.Chrome() driver.get(loginurl) # 方式1 通过填充用户名和密码 # driver.find_element_by_name('username').clear() # 获取用户名框 # driver.find_element_by_name('username').send_keys(u'username') # 填充用户名 # driver.find_element_by_name('password').clear() # 获取密码框 # driver.find_element_by_name('password').send_keys(u'password') # 填充密码 # time.sleep(10) # 执行休眠10s等待浏览器的加载 # input("检查网页是否有验证码要输入,有就在网页输入验证码,输入完后在编辑器中回车;如果无验证码,则直接回车") # 非常关键,有时候知乎会在输入密码后弹出验证码,这一步可将代码执行暂时停滞 # driver.find_element_by_css_selector("button[class='Button SignFlow-submitButton Button--primary Button--blue']").click() # 点击登录按钮 # 方式2 直接通过扫描二维码,如果不是要求全自动化,建议用这个,非常直接 # 毕竟我们这一步只是想保存登录后的cookies,至于用何种方式登录,可以不必过于计较 time.sleep(10) # 同样休眠10s等待页面 input("请页面二维码,并确认登录后,点击回车:") #点击二维码手机扫描登录 # 通过上述的方式实现登录后,其实我们的cookies在浏览器中已经有了,我们要做的就是获取 cookies = driver.get_cookies() # Selenium为我们提供了get_cookies来获取登录cookies driver.close() # 获取cookies便可以关闭浏览器 # 然后的关键就是保存cookies,之后请求从文件中读取cookies就可以省去每次都要登录一次的 # 当然可以把cookies返回回去,但是之后的每次请求都要先执行一次login没有发挥cookies的作用 jsonCookies=json.dumps(cookies) # 通过json将cookies写入文件 with open('zhihuCookies.json','w') as f: f.write(jsonCookies) print(cookies) # return cookies # Scrapy使用保存ookies请求发现模块,看是否是登录之后的状态 def question(self,response): with open('zhihu_find.html','w',encoding='utf-8') as f: f.write(response.text) #写入文件,保存成.html文件 pass def parse(self, response): pass # scrapy请求的开始时start_request def start_requests(self): zhihu_findUrl = 'https://www.zhihu.com/explore' self.loginZhihu() # 首次使用,先执行login,保存cookies之后便可以注释, # 毕竟每次执行都要登录还是挺麻烦的,我们要充分利用cookies的作用 # 从文件中获取保存的cookies with open('zhihuCookies.json','r',encoding='utf-8') as f: listcookies=json.loads(f.read()) # 获取cookies # 把获取的cookies处理成dict类型 cookies_dict = dict() for cookie in listcookies: # 在保存成dict时,我们其实只要cookies中的name和value,而domain等其他都可以不要 cookies_dict[cookie['name']] = cookie['value'] print(cookies_dict) # Scrapy发起其他页面请求时,带上cookies=cookies_dict即可,同时记得带上header值, yield scrapy.Request(url=zhihu_findUrl,cookies=cookies_dict,callback=self.question,headers=self.headers)

通过上面的方法就可以实现,在请求其他页面时也是登录之后的状态,毕竟cookies作用之一就是记录状态的,当然保存cookies之后你也可以试试将login_zhihu()的方法注释,去请求其他页面,只要我们的cookies不过期,效果都是一样的。效果如下:

当然,除了通过保存成dict类型,在请求时通过cookies=cookies_dict外,我们可以连串成字符串,添加到headers头部中,代码如下:

with open('zhihuCookies.json','r',encoding='utf-8') as f: listcookies=json.loads(f.read()) cookie=[item["name"]+"="+item["value"] for item in listcookies] cookiestr="; ".join(item for item in cookie) print(cookiestr) headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0", "HOST": "www.zhihu.com", "cookie": cookiestr #从文件中获取并拼接的cookies } # 放在header是发起请求 yield scrapy.Request(url=zhihu_findUrl,callback=self.question,headers=headers)

这种方法应该也是可行的,到时我到现在还没有成功过,不知道是不是拼接cookies是不是哪里写错了,大家成了帮我看看。

需要源代码或者有其他指教,欢迎微信添加“第一行Python代码”,一起学习python代码。

转载请注明原文地址: https://www.6miu.com/read-3100059.html

最新回复(0)