【python爬虫01】使用requests库模拟登录知乎

最近入坑python爬虫…简单记录一下我的爬虫经历。一开始是因为经常在知乎上看到各种关于爬虫的资料,于是自己也想尝试一下,既然这个念头是在知乎上产生的,那么我的爬虫之旅就从爬取知乎开始吧。:)

 

要开始写爬虫首先需要掌握以下几点:

①   网站的请求,响应等基本知识。

②   学会分析网站,各种抓包工具的使用,方便我们分析网站的交互。

由于我们是要登录知乎,自然需要知道请求的参数以及该向哪个url发送请求,我是通过chrone浏览器自带的开发者工具查看的,你也可以使用其他的抓包工具。

 

在输入账号密码登录之后,这里可以获取到所有的请求,其中就包括了我们的登录请求,稍微找一下就发现了。在这里我们可以看到我们需要请求的url,以及需要发送的数据,也可以获得我们的请求头。

 


在我们浏览网页的时候,浏览器向url所在的服务器发出请求,服务器通过识别请求报文中的请求头来判断访问者的身份,通常在爬虫中,我们经常需要做的就是伪造请求头伪装成浏览器,防止被识别出爬虫身份。如下面代码,就是我们构造的请求头(可以通过抓包工具获取),在发出请求的时候带上这个请求头,我们的爬虫就不会被轻易地拦截了~

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
    'Accept-Encoding': 'gzip, deflate,sdch, br',
    'Accept-Language': 'zh-CN,zh;q=0.8',
    'Connection': 'keep-alive',
    'Host': 'www.zhihu.com',
    'Origin': 'https://www.zhihu.com',
    'Referer': 'https://www.zhihu.com/',
    'User-Agent': 'Mozilla/5.0 (X11;Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
    'x-hd-token': 'hello',
}


一番分析之后发现使用手机号登陆的话是向https://www.zhihu.com/login/phone_num这个链接发出请求,并且需要的参数是_xsrf,password,phone_num,captcha_type。然而这里我构造之后发现并不能登陆成功,查看了别人的代码之后才发现如果爬虫的话captcha_type要换成captcha,也就是说会有一个验证码…实际所需参数是_xsrf,password,phone_num,cpatcha。(原因我也不清楚..他们是如何发现需要带一个captcha的呢??)

post_data = {
    '_xsrf': '***',
    'password': password,
    'captcha': '***',
    'phone_num': username,
}


这就是我们需要构造提交的参数,那个_xsrf是什么呢?主要是为了防止跨站脚本攻击用的,通常在网页可以获得。验证码我采用的是手动输入的方法,需要将验证码图片下载下来,人工识别后再手动输入。具体代码如下

# 下载验证码
with open("../code.jpg", 'wb') as w:
p=self.__session.get(url="https://www.zhihu.com/captcha.gif?r=1495546872530&type=login",headers=self.headers)
    w.write(p.content)
code = input("请输入验证码:")


请求成功之后我们会得到一串json数据,告诉我们登录成功或者失败

"""
        验证码错误返回:
        {'errcode': 1991829, 'r': 1, 'data': {'captcha': '请提交正确的验证码 :('}, 'msg': '请提交正确的验证码 :('}
        登录成功返回:
        {'r': 0, 'msg': '登陆成功'}
        """

为了不想每次都登录,我们可以把cookie存下来,下次登录的时候就不用再重复一遍登录操作了。

def __saveCookie(self):
    """cookies 序列化到文件
    即把dict对象转化成字符串保存
    """
    with open(self.cookieFile, "w")as output:
        cookies = self.__session.cookies.get_dict()
        json.dump(cookies, output)
        print("已在同目录下生成cookie文件:", self.cookieFile)
 

登录成功之后,我们的session就保留了登录信息,我们利用session就可以进行登录后的各种操作。通过输出我们发现已经成功抓取到了知乎首页



具体代码:

# -*- coding: utf-8 -*-
import requests
import re
import json
import sys
import os
import time
class ZhiHuClient(object):
    headers = {
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
        'Accept-Encoding': 'gzip, deflate, sdch, br',
        'Accept-Language': 'zh-CN,zh;q=0.8',
        'Connection': 'keep-alive',
        'Host': 'www.zhihu.com',
        'Origin': 'https://www.zhihu.com',
        'Referer': 'https://www.zhihu.com/',
        'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36',
        'x-hd-token': 'hello',
    }
    cookieFile = os.path.join(sys.path[0], "cookie")
    def __init__(self):
        os.chdir(sys.path[0])  # 设置脚本所在目录为当前工作目录
        self.__session = requests.Session()
        # 若已经有 cookie 则直接登录
        self.__cookie = self.__loadCookie()
        print(self.__cookie)
        if self.__cookie:
            print("检测到cookie文件,直接使用cookie登录")
            self.__session.cookies.update(self.__cookie)
        else:
            print("没有找到cookie文件,请调用login方法登录一次!")
    def __saveCookie(self):
        """cookies 序列化到文件
        即把dict对象转化成字符串保存
        """
        with open(self.cookieFile, "w") as output:
            cookies = self.__session.cookies.get_dict()
            json.dump(cookies, output)
            print("已在同目录下生成cookie文件:", self.cookieFile)
    def __loadCookie(self):
        if os.path.exists(self.cookieFile):
            with open(self.cookieFile, "r") as f:
                cookie = json.load(f)
                return cookie
        return None
    def getSession(self):
        return self.__session
    def open(self, url, delay=0, timeout=10):
        if delay:
            time.sleep(delay)
        return self.__session.get(url,headers=self.headers, timeout=timeout)

    def login(self, username, password):
        """
        验证码错误返回:
        {'errcode': 1991829, 'r': 1, 'data': {'captcha': '请提交正确的验证码 :('}, 'msg': '请提交正确的验证码 :('}
        登录成功返回:
        {'r': 0, 'msg': '登陆成功'}
        """
        # 下面写入账号密码
        post_data = {
            '_xsrf': '***',
            'password': password,
            'captcha': '***',
            'phone_num': username,
        }
        self.__username = username
        self.__password = password
        page = self.__session.get(url="https://www.zhihu.com/#signin", headers=self.headers)
        parser = re.compile(u'<input type="hidden" name="_xsrf" value="(.*?)"/>', re.S)
        xsrf = re.findall(parser, page.text)[0]
        self.headers['X-Xsrftoken'] = xsrf
        post_data['_xsrf'] = xsrf
        print(post_data)
        # 下载验证码
        with open("../code.jpg", 'wb') as w:
            p = self.__session.get(url="https://www.zhihu.com/captcha.gif?r=1495546872530&type=login", headers=self.headers)
            w.write(p.content)
        code = input("请输入验证码:")
        if not code:
            sys.exit(1)
        post_data['captcha'] = code
            # 发送POST请求
        res = self.__session.post(url='https://www.zhihu.com/login/phone_num',data=post_data,headers=self.headers)
        # print(res.text) # 输出脚本信息,调试用
        if res.json()["r"] == 0:
            print("登录成功")
            self.__saveCookie()
        else:
            print("登录失败")
            print("错误信息 --->", res.json()["msg"])
#cookie=login().cookies.get_dict()
client = ZhiHuClient()
#如果没有cookie需要在这里先调用client.login(),出现cookie过期的情况可能登陆不上,可以手动将cookie删掉重新登陆
print(client.open("https://www.zhihu.com").content.decode("utf8"))

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值