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

一、前言

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

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

那这样,我们要怎么才能登录知乎,于似乎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不过期,效果都是一样的。效果如下:

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

当然,除了通过保存成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代码。

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

你可能感兴趣的:(Python爬虫)