Python3以GitHub为例来实现模拟登录和爬取的实例讲解


Posted in Python onJuly 30, 2020

我们先以一个最简单的实例来了解模拟登录后页面的抓取过程,其原理在于模拟登录后 Cookies 的维护。

1. 本节目标

本节将讲解以 GitHub 为例来实现模拟登录的过程,同时爬取登录后才可以访问的页面信息,如好友动态、个人信息等内容。

我们应该都听说过 GitHub,如果在我们在 Github 上关注了某些人,在登录之后就会看到他们最近的动态信息,比如他们最近收藏了哪个 Repository,创建了哪个组织,推送了哪些代码。但是退出登录之后,我们就无法再看到这些信息。

如果希望爬取 GitHub 上所关注人的最近动态,我们就需要模拟登录 GitHub。

2. 环境准备

请确保已经安装好了 requests 和 lxml 库,如没有安装可以参考第 1 章的安装说明。

3. 分析登录过程

首先要分析登录的过程,需要探究后台的登录请求是怎样发送的,登录之后又有怎样的处理过程。

如果已经登录 GitHub,先退出登录,同时清除 Cookies。

打开 GitHub 的登录页面,链接为 https://github.com/login,输入 GitHub 的用户名和密码,打开开发者工具,将 Preserve Log 选项勾选上,这表示显示持续日志,如图 10-1 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

点击登录按钮,这时便会看到开发者工具下方显示了各个请求过程,如图 10-2 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

点击第一个请求,进入其详情页面,如图 10-3 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

可以看到请求的 URL 为 https://github.com/session,请求方式为 POST。再往下看,我们观察到它的 Form Data 和 Headers 这两部分内容,如图 10-4 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

Headers 里面包含了 Cookies、Host、Origin、Referer、User-Agent 等信息。Form Data 包含了 5 个字段,commit 是固定的字符串 Sign in,utf8 是一个勾选字符,authenticity_token 较长,其初步判断是一个 Base64 加密的字符串,login 是登录的用户名,password 是登录的密码。

综上所述,我们现在无法直接构造的内容有 Cookies 和 authenticity_token。下面我们再来探寻一下这两部分内容如何获取。

在登录之前我们会访问到一个登录页面,此页面是通过 GET 形式访问的。输入用户名密码,点击登录按钮,浏览器发送这两部分信息,也就是说 Cookies 和 authenticity_token 一定是在访问登录页的时候设置的。

这时再退出登录,回到登录页,同时清空 Cookies,重新访问登录页,截获发生的请求,如图 10-5 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

访问登录页面的请求如图所示,Response Headers 有一个 Set-Cookie 字段。这就是设置 Cookies 的过程。

另外,我们发现 Response Headers 没有和 authenticity_token 相关的信息,所以可能 authenticity_token 还隐藏在其他的地方或者是计算出来的。我们再从网页的源码探寻,搜索相关字段,发现源代码里面隐藏着此信息,它是一个隐藏式表单元素,如图 10-6 所示。

Python3以GitHub为例来实现模拟登录和爬取的实例讲解

现在我们已经获取到所有信息,接下来实现模拟登录。

4. 代码实战

首先我们定义一个 Login 类,初始化一些变量:

class Login(object):
    def __init__(self):
        self.headers = {
            'Referer': 'https://github.com/',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) 
            Chrome/57.0.2987.133 Safari/537.36',
            'Host': 'github.com'
        }
        self.login_url = 'https://github.com/login'
        self.post_url = 'https://github.com/session'
        self.logined_url = 'https://github.com/settings/profile'
        self.session = requests.Session()

这里最重要的一个变量就是 requests 库的 Session,它可以帮助我们维持一个会话,而且可以自动处理 Cookies,我们不用再去担心 Cookies 的问题。

接下来,访问登录页面要完成两件事:一是通过此页面获取初始的 Cookies,二是提取出 authenticity_token。

在这里我们实现一个 token() 方法,如下所示:

from lxml import etree
def token(self):
    response = self.session.get(self.login_url, headers=self.headers)
    selector = etree.HTML(response.text)
    token = selector.xpath('//div/input[2]/@value')[0]
    return token

我们用 Session 对象的 get() 方法访问 GitHub 的登录页面,然后用 XPath 解析出登录所需的 authenticity_token 信息并返回。

现在已经获取初始的 Cookies 和 authenticity_token,开始模拟登录,实现一个 login() 方法,如下所示:

def login(self, email, password):
    post_data = {
        'commit': 'Sign in',
        'utf8': '✓',
        'authenticity_token': self.token(),
        'login': email,
        'password': password
    }
    response = self.session.post(self.post_url, data=post_data, headers=self.headers)
    if response.status_code == 200:
        self.dynamics(response.text)
    response = self.session.get(self.logined_url, headers=self.headers)
    if response.status_code == 200:
        self.profile(response.text)

首先构造一个表单,复制各个字段,其中 email 和 password 是以变量的形式传递。然后再用 Session 对象的 post() 方法模拟登录即可。由于 requests 自动处理了重定向信息,我们登录成功后就可以直接跳转到首页,首页会显示所关注人的动态信息,得到响应之后我们用 dynamics() 方法来对其进行处理。接下来再用 Session 对象请求个人详情页,然后用 profile() 方法来处理个人详情页信息。

其中,dynamics() 方法和 profile() 方法的实现如下所示:

def dynamics(self, html):
    selector = etree.HTML(html)
    dynamics = selector.xpath('//div[contains(@class, "news")]//div[contains(@class, "alert")]')
    for item in dynamics:
        dynamic = ' '.join(item.xpath('.//div[@class="title"]//text()')).strip()
        print(dynamic)
def profile(self, html):
    selector = etree.HTML(html)
    name = selector.xpath('//input[@id="user_profile_name"]/@value')[0]
    email = selector.xpath('//select[@id="user_profile_email"]/option[@value!=""]/text()')
    print(name, email)

在这里,我们仍然使用 XPath 对信息进行提取。在 dynamics() 方法里,我们提取了所有的动态信息,然后将其遍历输出。在 prifile() 方法里,我们提取了个人的昵称和绑定的邮箱,然后将其输出。

这样,整个类的编写就完成了。

5. 运行

我们新建一个 Login 对象,然后运行程序,如下所示:

if __name__ == "__main__":
    login = Login()
    login.login(email='cqc@cuiqingcai.com', password='password')

在 login() 方法传入用户名和密码,实现模拟登录。

可以看到控制台有类似如下输出:

GrahamCampbell  starred  nunomaduro/zero-framework
GrahamCampbell  starred  nunomaduro/laravel-zero
happyAnger6  created repository  happyAnger6/nodejs_chatroom
viosey  starred  nitely/Spirit
lbgws2  starred  Germey/TaobaoMM
EasyChris  starred  ageitgey/face_recognition
callmewhy  starred  macmade/GitHubUpdates
sindresorhus  starred  sholladay/squatter
SamyPesse  starred  graphcool/chromeless
wbotelhos  starred  tkadlec/grunt-perfbudget
wbotelhos  created repository  wbotelhos/eggy
leohxj  starred  MacGesture/MacGesture
GrahamCampbell  starred  GrahamCampbell/Analyzer
EasyChris  starred  golang/go
mitulgolakiya  starred  veltman/flubber
liaoyuming  pushed to  student  at  Germey/SecurityCourse
leohxj  starred  jasonslyvia/a-cartoon-intro-to-redux-cn
ruanyf  starred  ericchiang/pup
ruanyf  starred  bpesquet/thejsway
louwailou  forked  Germey/ScrapyTutorial  to  louwailou/ScrapyTutorial
Lving  forked  shadowsocksr-backup/shadowsocksr  to  Lving/shadowsocksr
qifuren1985  starred  Germey/ADSLProxyPool
QWp6t  starred  laravel/framework
Germey ['1016903103@qq.com', 'cqc@cuiqingcai.com']

可以发现,我们成功获取到关注的人的动态信息和个人的昵称及绑定邮箱。模拟登录成功!

6. 本节代码

本节代码地址:https://github.com/Python3WebSpider/GithubLogin。

7. 结语

我们利用 requests 的 Session 实现了模拟登录操作,其中最重要的还是分析思路,只要各个参数都成功获取,那么模拟登录是没有问题的。

登录成功,这就相当于建立了一个 Session 会话,Session 对象维护着 Cookies 的信息,直接请求就会得到模拟登录成功后的页面。

以上就是Python3以GitHub为例来实现模拟登录和爬取的实例讲解的详细内容,更多关于Python3爬虫以GitHub为例来实现模拟登录和爬取的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python实现计算文件夹下.h和.cpp文件的总行数
Apr 23 Python
让Python代码更快运行的5种方法
Jun 21 Python
深入剖析Python的爬虫框架Scrapy的结构与运作流程
Jan 20 Python
python gdal安装与简单使用
Aug 01 Python
Python学习笔记之While循环用法分析
Aug 14 Python
python中web框架的自定义创建
Sep 08 Python
pytorch GAN伪造手写体mnist数据集方式
Jan 10 Python
Python类的绑定方法和非绑定方法实例解析
Mar 04 Python
Python在终端通过pip安装好包以后在Pycharm中依然无法使用的问题(三种解决方案)
Mar 10 Python
pycharm 实现本地写代码,服务器运行的操作
Jun 08 Python
Python实现石头剪刀布游戏
Jan 20 Python
详解修改Anaconda中的Jupyter Notebook默认工作路径的三种方式
Jan 24 Python
Python如何实现线程间通信
Jul 30 #Python
Python如何输出警告信息
Jul 30 #Python
Python设计密码强度校验程序
Jul 30 #Python
详解Pandas 处理缺失值指令大全
Jul 30 #Python
Python 爬虫的原理
Jul 30 #Python
Python爬虫与反爬虫大战
Jul 30 #Python
Python如何将装饰器定义为类
Jul 30 #Python
You might like
计数器详细设计
2006/10/09 PHP
php smarty 二级分类代码和模版循环例子
2011/06/01 PHP
浅谈关于PHP解决图片无损压缩的问题
2017/09/01 PHP
php获取用户真实IP和防刷机制的实例代码
2018/11/28 PHP
Mootools 1.2教程 函数
2009/09/15 Javascript
线路分流自动智能跳转代码,自动选择最快镜像网站(js)
2011/10/31 Javascript
js跨浏览器实现将字符串转化为xml对象的方法
2013/09/25 Javascript
JavaScript设计模式之抽象工厂模式介绍
2014/12/28 Javascript
jQuery实现可高亮显示的二级CSS菜单效果
2015/09/01 Javascript
JS多文件上传的实例代码
2017/01/11 Javascript
微信小程序 PHP生成带参数二维码
2017/02/21 Javascript
JS实现浏览器打印、打印预览示例
2017/02/28 Javascript
js 判断一个数字是不是2的n次方幂的实例
2017/11/26 Javascript
微信小程序实现单个卡片左滑显示按钮并防止上下滑动干扰功能
2019/12/06 Javascript
javascript代码实现简易计算器
2021/01/25 Javascript
详解Python编程中包的概念与管理
2015/10/16 Python
TF-IDF与余弦相似性的应用(一) 自动提取关键词
2017/12/21 Python
浅谈python爬虫使用Selenium模拟浏览器行为
2018/02/23 Python
Python Requests库基本用法示例
2018/08/20 Python
python根据文章标题内容自动生成摘要的实例
2019/02/21 Python
Python闭包和装饰器用法实例详解
2019/05/22 Python
pygame实现成语填空游戏
2019/10/29 Python
python3.4中清屏的处理方法
2020/07/06 Python
sublime3之内网安装python插件Anaconda的流程
2020/11/10 Python
html5 Canvas画图教程(10)—把面拆成线条模拟出圆角矩形
2013/01/09 HTML / CSS
凯特·丝蓓英国官网:Kate Spade英国
2016/11/07 全球购物
美国专业汽车音响和移动电子产品零售商:Car Toys
2019/05/13 全球购物
男女朋友协议书
2014/04/23 职场文书
网络技术专业求职信
2014/07/13 职场文书
2014副局长群众路线对照检查材料思想汇报
2014/09/22 职场文书
教师党员批评与自我批评发言稿
2014/10/15 职场文书
2017元旦晚会开幕词
2016/03/03 职场文书
Python实现天气查询软件
2021/06/07 Python
Python机器学习之基于Pytorch实现猫狗分类
2021/06/08 Python
微信小程序scroll-view不能左右滑动问题的解决方法
2021/07/09 Javascript
MySQL中utf8mb4排序规则示例
2021/08/02 MySQL