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 相关文章推荐
Cython 三分钟入门教程
Sep 17 Python
举例讲解Python中的迭代器、生成器与列表解析用法
Mar 20 Python
python3获取两个日期之间所有日期,以及比较大小的实例
Apr 08 Python
python XlsxWriter模块创建aexcel表格的实例讲解
May 03 Python
使用Python AIML搭建聊天机器人的方法示例
Jul 09 Python
使用Python创建简单的HTTP服务器的方法步骤
Apr 26 Python
使用Python实现Wake On Lan远程开机功能
Jan 22 Python
Python tkinter布局与按钮间距设置方式
Mar 04 Python
Python 程序报错崩溃后如何倒回到崩溃的位置(推荐)
Jun 23 Python
python爬虫数据保存到mongoDB的实例方法
Jul 28 Python
matplotlib自定义鼠标光标坐标格式的实现
Jan 08 Python
python 单机五子棋对战游戏
Apr 28 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
PHP - Html Transfer Code
2006/10/09 PHP
PHP 的ArrayAccess接口 像数组一样来访问你的PHP对象
2010/10/12 PHP
关于PHP模板Smarty的初级使用方法以及心得分享
2013/06/21 PHP
php-perl哈希算法实现(times33哈希算法)
2013/12/30 PHP
php将服务端的文件读出来显示在web页面实例
2016/10/31 PHP
PHP设置images目录不充许http访问的方法
2016/11/01 PHP
php从身份证获取性别和出生年月
2017/02/09 PHP
javascript IFrame 强制刷新代码
2009/07/23 Javascript
javascript下高性能字符串连接StringBuffer类
2010/08/16 Javascript
javascript 快速排序函数代码
2012/05/30 Javascript
基于jquery库的tab新形式使用
2012/11/16 Javascript
jquery遍历数组与筛选数组的方法
2013/11/05 Javascript
JavaScript实现的一个倒计时的类
2015/03/12 Javascript
在JavaScript中处理时间之getHours()方法的使用
2015/06/10 Javascript
Node.js使用NodeMailer发送邮件实例代码
2017/03/06 Javascript
nodejs实现大文件(在线视频)的读取
2020/10/16 NodeJs
如何为你的JS项目添加智能提示与类型检查详解
2019/03/12 Javascript
详解如何提升JSON.stringify()的性能
2019/06/12 Javascript
Python绘制七段数码管实例代码
2017/12/20 Python
python 实现目录复制的三种小结
2019/12/04 Python
keras K.function获取某层的输出操作
2020/06/29 Python
Python基础进阶之海量表情包多线程爬虫功能的实现
2020/12/17 Python
香港连卡佛百货官网:Lane Crawford
2019/09/04 全球购物
旅游管理毕业生自荐信
2013/11/05 职场文书
好的演讲稿开场白
2013/12/30 职场文书
珍惜水资源建议书
2014/03/12 职场文书
竞选演讲稿范文大全
2014/05/12 职场文书
小学生迎国庆演讲稿
2014/09/05 职场文书
工作疏忽、懈怠的检讨书
2014/09/11 职场文书
检查机关领导群众路线教育实践活动个人整改措施
2014/10/28 职场文书
队列队形口号
2015/12/25 职场文书
HR必备:超全面的薪酬待遇管理方案!
2019/07/12 职场文书
MySQL8.0无法启动3534的解决方法
2021/06/03 MySQL
Python Pandas模块实现数据的统计分析的方法
2021/06/24 Python
在NumPy中深拷贝和浅拷贝相关操作的定义和背后的原理
2022/04/14 Python
IIS服务器中设置HTTP重定向访问HTTPS
2022/04/29 Servers