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 相关文章推荐
恢复百度云盘本地误删的文件脚本(简单方法)
Oct 21 Python
python如何生成各种随机分布图
Aug 27 Python
selenium+python环境配置教程详解
May 28 Python
python里 super类的工作原理详解
Jun 19 Python
python实现截取屏幕保存文件,删除N天前截图的例子
Aug 27 Python
Python paramiko模块使用解析(实现ssh)
Aug 30 Python
基于python监控程序是否关闭
Jan 14 Python
opencv python 图片读取与显示图片窗口未响应问题的解决
Apr 24 Python
python调用API接口实现登陆短信验证
May 10 Python
学python最电脑配置有要求么
Jul 05 Python
pytest进阶教程之fixture函数详解
Mar 29 Python
健身房被搭讪?用python写了个小米计时器助人为乐
Jun 08 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中空字符串和0之间的关系
2016/10/23 PHP
PHP经典设计模式之依赖注入定义与用法详解
2019/05/21 PHP
尽可能写"友好"的"Javascript"代码
2007/01/09 Javascript
基于Jquery的文字自动截取(提供源代码)
2011/08/09 Javascript
js中prototype用法详细介绍
2013/11/14 Javascript
jquery简单实现带渐显效果的选项卡菜单代码
2015/09/01 Javascript
AngularJS 2.0入门权威指南
2016/10/08 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
javascript十六进制数字和ASCII字符之间的转换方法
2016/12/27 Javascript
angular中实现控制器之间传递参数的方式
2017/04/24 Javascript
JavaScript数据结构学习之数组、栈与队列
2017/05/02 Javascript
jQuery制作全屏宽度固定高度轮播图(实例讲解)
2017/07/08 jQuery
Vuejs 单文件组件实例详解
2018/02/09 Javascript
js中Generator函数的深入讲解
2019/04/07 Javascript
微信小程序实现图片上传
2019/05/23 Javascript
解决antd datepicker 获取时间默认少8个小时的问题
2020/10/29 Javascript
[51:10]VP vs VGJ.S 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
在Django框架中设置语言偏好的教程
2015/07/27 Python
django 2.0更新的10条注意事项总结
2018/01/05 Python
python+pillow绘制矩阵盖尔圆简单实例
2018/01/16 Python
python标记语句块使用方法总结
2019/08/05 Python
python线程信号量semaphore使用解析
2019/11/30 Python
Python中如何将一个类方法变为多个方法
2019/12/30 Python
pycharm最新激活码有效期至2100年(亲测可用)
2021/02/05 Python
Python爬虫制作翻译程序的示例代码
2021/02/22 Python
css3 线性渐变和径向渐变示例附图
2014/04/08 HTML / CSS
皇马官方商城:Real Madrid Store
2016/09/02 全球购物
英国电子产品购物网站:TobyDeals
2018/07/30 全球购物
《鹬蚌相争》教学反思
2014/04/22 职场文书
单方离婚协议书范本(2014版)
2014/09/30 职场文书
2015最新学生自我评价范文
2015/03/03 职场文书
投诉信回复范文
2015/07/03 职场文书
反腐倡廉心得体会2016
2016/01/13 职场文书
三严三实·严以律己心得体会
2016/01/13 职场文书
关于Vue Router的10条高级技巧总结
2021/05/06 Vue.js