• Scrapy基础(十四)————知乎模拟登陆


    #-*-coding:utf-8 -*-
    __author__ = "ruoniao"
    __date__ = "2017/5/31 20:59"

      之前我们通过爬取伯乐在线的文章,伯乐在线对爬取没有什么限制,这次爬取知乎,就有了爬取限制,首先就是
    登录限制;为破解限制,首先就是模拟登录

    模拟登陆首先要明白的就是session和cookie机制:   

    简单的说(个人理解):
      http是一种无状态的协议,为解决用户每次都需要输入密码登录的烦恼,也为了服务器能够记住每次请求的浏览器,就有了会话机制,

    就是每次对话不需要问你是谁,浏览器只需要将服务器原先发送给浏览器的ID原封不动的还给服务器,这样服务器就可以在自己的
    数据库中查找这个ID就可以,而只有这个ID是没用的,若想要用户登录,还需要用用户名和密码,加密后以cookie的形式存储在本地,

    下次请求直接发送给服务器就行

      总之:为了服务器和浏览器之间互相确认身份,服务器生成一个session_id并且保存在服务器,还有给浏览器一份,浏览器将这个session_id写入cookie,

    发送给服务器,服务器对照自己保存在本地的,就能互相确认身份;不同的是:cookie中还带了用户的个人信息等

        
            cookie是存储在本地的记录某个网站的个人信息的机制
            session是存储在服务器中的记录某个浏览器(用户)的信息的机制,更安全;
    具体理解可参考这篇文章
     

    不同的网站模拟登录的策略不同,不同的网站要进行不同的分析;但都是大同小异;做过web的明白,无非就是用户的验证;较难的就是识别验证码了 

    知乎的登录破解   

        

        1:这里遇到了坑,因为在firebug中测试时,post到url时没有填写验证码;而通过requests post到URL
       具体参数时报错:验证码错误,这就很纳闷了;
        2:原来:当向首页get时,因为有cookies,所以登录时就不需要填写验证码;通过代码时没有加cookies,需要填写验证码
        而验证码不好识别,只能更换思路
        3: 模拟浏览器的行为,若当初为取的xsrf时get带上cookie,下次登录就不需要验证码了
        4:那么怎么才能将cookie post到URL呢?了解requests.post()方法的知道:post()可带的参数很多
        其中cookies= {}或CookieJar
        5:将cookies以字典的形式post方便操作,只需要在firebug中的cookies复制为字典的格式
           以CookieJar的形式:因为cookie是保存在硬盘的,可以参考这篇博文

        6:因为cookie是有生存周期的额,为了下面重新登录,可以将登录后的cookie以txt的形式保存在本地,下次直接load就可以

    实例代码注释

      1 import requests
      2 #适合python2和python3版本的导包
      3 try:
      4     import cookielib
      5 except:
      6     import http.cookiejar as cookielib
      7 import re
      8 from urllib import parse, request
      9 
     10 #使用会话机制向url发送request,提高效率,不必每次都发请求(类比浏览器直接在本标签页操作,不需重新产生新的标签页)
     11 session = requests.session()
     12 #将会话产生的cookies保存在本地
     13 session.cookies = cookielib.LWPCookieJar(filename="cookies.txt")
     14 
     15 #浏览器版本信息,目的是伪装成一个浏览器,让服务器认为我们的代码是一个浏览器请求而不是爬虫,避免被拒绝
     16 headers = {
     17     "User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0",
     18     "Host":"www.zhihu.com",
     19     "Referer":"https://www.zhihu.com/",
     20 }
     21 
     22 #获取登录xsrf
     23 def get_xsrf():
     24 
     25     url = "https://www.zhihu.com/#signin"
     26 
     27     try:
     28         #带上cookie,避免产生验证码识别
     29         req = session.get(url=url,cookies=cookies,headers=headers)
     30         #通过正则表达式解析出 xsrf 类比csrf机制
     31         xsrf = re.findall('<input type="hidden" name="_xsrf" value="(.*?)"/>',req.text)
     32         if xsrf:
     33             xsrf = xsrf[0]
     34             print(xsrf)
     35             return xsrf
     36         else:
     37             return xsrf
     38     except Exception as e:
     39         print(e)
     40         print("failed download")
     41 
     42 
     43 
     44 #知乎登录
     45 def zhihu_login(account,password):
     46 
     47     #首先获取xsrf
     48     xsrf = get_xsrf()
     49     #判断是手机号:以手机号登录,提交表单和提交URL不同,构造不同的URL和表单
     50     if re.match("d{10}",account):
     51 
     52         url = "https://www.zhihu.com/login/phone_num"
     53         data={
     54             "_xsrf":xsrf,
     55             'remember_me': 'true',
     56             "password":password,
     57             "phone_num":account
     58         }
     59     if '@' in account:
     60         url = "https://www.zhihu.com/login/email"
     61         data={
     62             "_xsrf":xsrf,
     63             'remember_me': 'true',
     64             "password":password,
     65             "email":account
     66         }
     67     #将获取到的xsrf加载到cookie中
     68     cookies["_xsrf"] = xsrf
     69     #带上表单,头信息,cookies申请登录
     70     r = session.post(url=url,data=data,headers=headers,cookies=cookies)
     71     print(r.text)
     72     #登录成功将cookies保存到本地
     73     session.cookies.save()
     74 
     75 
     76 #获取首页;登录后可直接获取,因为session中已经(带了)加载了cookie
     77 def get_index():
     78     response = session.get("https://www.zhihu.com/",headers=headers)
     79     print(response.status_code)
     80     #将首页写入本地文件
     81     with open("index_page.html","wb") as f:
     82         f.write(response.text.encode("utf-8"))
     83     print("write ok")
     84 
     85 #查看登录状态;向一个只有登录的页面get,若登录会返回200;否则304,会重定向到登录页(重定向后会返回200)
     86 def is_login():
     87     url = "https://www.zhihu.com/inbox"
     88     #allow_redirects  禁止重定向
     89     response  = session.get(url=url,headers=headers,allow_redirects=False)
     90     #判断是否登录
     91     if response.status_code != 200:
     92         return False
     93     else:
     94         return True
     95 
     96 
     97 #先尝试本地cookie登录,不成功使用浏览器copy下来的cookies重新登录,生成本地cookies
     98 try:
     99     #先尝试加载之前保存在本地的cookies
    100     session.cookies.load(ignore_discard=True)
    101     print("cookies 已记载")
    102 except:
    103     #没加载就重新登录
    104     print("cookie 未加载")
    105     #这个cookie是从firebug中复制来的
    106     cookies = {
    107     "d_c0":"",
    108     "l_cap_id":"",
    109     "r_cap_id":"",
    110     "cap_id":"",
    111     "_zap":"",
    112     "__utmc":"",
    113     "__utmb":"",
    114     "__utmv":"",
    115     "__utma":"",
    116     "__utmz":"",
    117     "q_c1":""118 
    119 }
    120     #调用登录函数,成功后会更新cookie到本地
    121     zhihu_login("342200377@qq.com","")
    122     #更新成功后重新加载cookies
    123     session.cookies.load(ignore_discard=True)
    124 
    125 
    126 print(is_login())







  • 相关阅读:
    使用Wireshark 抓取数据包
    React Native 开发之 (07) 常用组件-View
    Swift开发之 (01) 语法
    React Native 开发之 (05) flexbox布局
    React Native 开发之 (06) JSX
    深入浅出Redis02 使用Redis数据库(String类型)
    React Native 开发之 (04) 例子讲解
    npm命令大全
    npm
    node.js
  • 原文地址:https://www.cnblogs.com/ruoniao/p/6935203.html
Copyright © 2020-2023  润新知