热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

模拟登陆Github

这里不讨论用GithubAPI的情况,仅仅以Github来说明模拟登陆先尝试用真实浏览器登陆,登陆成功后在开发者工具的Network选项卡中捕获Session文件。可以看到,登陆所

这里不讨论用 Github API 的情况,仅仅以 Github 来说明模拟登陆

先尝试用真实浏览器登陆,登陆成功后在开发者工具的 Network 选项卡中捕获 Session 文件。可以看到,登陆所需要的数据不仅仅是 email(或用户名) 和密码,还需要其它的 3 个字段,而这 3 个字段普通用户在真实浏览器中是无法填写的(也无需填写,这仨字段会自动附加到表单中提交)。

《模拟登陆Github》

其中的 commit、utf8 的值是不变的,只有 authenticity_token 字段的值是每次登陆都不一样的(为的就是区分人类与爬虫程序),authenticity_token 字段是在 https://github.com/login (登陆页面,未登陆状态)的 from 元素下的一个隐含字段(不显示在浏览器中),其 type 属性值为 hidden

下图展示了(重新)登陆页面的源码,其中 type 属性为 hidden 的 input 字段中的 authenticity_token 属性的值就是需要提取出来作为表单数据的一部分提交至服务器

《模拟登陆Github》

从下图可以看到响应码(Status Code)是 302 found 表示重定向跳转至其它 url,这里跳转至 https://github.com,也就是说,登陆成功后就跳转至 Github 首页(即个人主页)

虽然是在 https://github.com/login 页面中登陆,但登陆时是向 https://github.com/session 提交表单数据,所以在 session 响应中可惜查看到已提交的表单数据。

《模拟登陆Github》

上图展示了登陆成功后,已提交的表单数据,可以发现 authenticity_token 字段的值和登陆前的值是一致的(email、password 字段由于是明文,所以这里打码了)

能保持登陆状态的原因是登陆成功后生成 COOKIEs 的功劳,不过 COOKIEs 一般不是永久有效的,如果希望长期处于登陆状态,需要每隔一段时间检测下 COOKIEs 是否还有效(或进行异常处理),失效的话就需要重新提交表单生成新的 COOKIEs。

代码实现

使用的库

  • requests
  • pyquery

携带 COOKIEs 模拟登陆 Github 的例子

代码中的表单数据 post_data 的 login、password 这俩字段分别需要改为自已的 email(或用户名)及密码

import requests
from pyquery import PyQuery as pq
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',
}
login_url = 'https://github.com/login'
post_url = 'https://github.com/session'
logined_url = 'https://github.com/settings/profile'
keys_url = "https://github.com/settings/keys"
# 提取隐含字段 authenticity_token 的值,登陆需要提交表单,而提交表单需要该值
login_r = requests.get(login_url, headers=headers)
doc = pq(login_r.text)
token = doc('input[name="authenticity_token"]').attr("value").strip()
print(token)
# 构造表单数据
post_data = {
'commit': 'Sign in',
'utf8': '✓',
'authenticity_token': token,
'login': email_or_name,
'password': password,
}
# 模拟登陆必须携带 COOKIEs
post_r = requests.post(post_url, data=post_data, headers=headers, COOKIEs=login_r.COOKIEs.get_dict())
# 可以发现响应的 url 是 https://github.com,而不是 https://github.com/session
# 因为模拟登陆成功后就 302 重定向跳转至 "https://github.com" 了
print(post_r.url)
doc = pq(post_r.text)
# 输出项目列表
print(doc("div.Box-body > ul > li").text().split())
# 请求其它 github 页面,只要附加了能维持登陆状态的 Cooikes 就可以访问只有登陆才可访问的页面内容
logined_r = requests.get(logined_url, headers=headers, COOKIEs=post_r.COOKIEs.get_dict())
doc = pq(logined_r.text)
page_title = doc("title").text()
user_profile_bio = doc("#user_profile_bio").text()
user_profile_company = doc("#user_profile_company").attr("value")
user_profile_location = doc("#user_profile_location").attr("value")
print(f"页面标题:{page_title}")
print(f"用户资料描述:{user_profile_bio}")
print(f"用户资料公司:{user_profile_company}")
print(f"用户资料地点:{user_profile_location}")
# 使用 logined_r 的 COOKIEs 也可以
keys_r = requests.get(keys_url, headers=headers, COOKIEs=post_r.COOKIEs.get_dict())
doc = pq(keys_r.text)
# SSH keys Title
doc('#ssh-key-29454773 strong.d-block').text()

显式传入 COOKIEs 、headers 还是挺麻烦的,万一有个请求没有携带完整的 COOKIEs,可能就无法得到正确的响应。

为了省略每次都要手动传入 COOKIEs 的麻烦,下面使用另一种方式模拟登陆 Github

利用 Session 对象维持 Github 模拟登陆状态

  1. 构造一个 session 对象;
  2. 使用 session 对象进行请求

代码

其中使用 session.headers 维持每次会话的 headers 不变

为了安全,利用内置模块 getpass 输入不可见的密码(注意密码一定不能错)

import getpass
import requests
from pyquery import PyQuery as pq
class Login(object):
def __init__(self):
base_url = 'https://github.com/'
# 登陆 url
self.login_url = base_url +'login'
# 提交表单的 api
self.post_url = base_url +'session'
# 个人资料页面的 url
self.logined_url = base_url +'settings/profile'
# 构造一个会话对象
self.session = requests.Session()
# 自定义请求头
self.session.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'
}
def token(self):
# 请求登陆页面
respOnse= self.session.get(self.login_url)
# 提取 authenticity_token 的 value,
doc = pq(response.text)
token = doc('input[name="authenticity_token"]').attr("value").strip()
return token def login(self, email, password):
token = self.token()
# 构造表单数据
post_data = {
'commit': 'Sign in',
'utf8': '✓',
'authenticity_token': token,
'login': email,
'password': password
}
# 发送 POST 请求,它会 302 重定向至 'https://github.com/',也就是响应 'https://github.com/' 的页面
respOnse= self.session.post(self.post_url, data=post_data)
# 可以发现 302 重定向至 'https://github.com/'
print(f"\n请求 url:{response.url}")
if response.status_code == 200:
print("status_code: 200")
self.home(response.text)
# 请求个人资料页
respOnse= self.session.get(self.logined_url)
if response.status_code == 200:
print("status_code: 200")
self.profile(response.text)
def home(self, html):
doc = pq(html)
# 提取用户名
user_name = doc("summary > span").text().strip()
print(f"用户名:{user_name}")
# 提取仓库列表
Repositories = doc("div.Box-body > ul > li").text().split()
for Repositorie in Repositories:
print(Repositorie) def profile(self, html):
doc = pq(html)
page_title = doc("title").text()
user_profile_bio = doc("#user_profile_bio").text()
user_profile_company = doc("#user_profile_company").attr("value")
user_profile_location = doc("#user_profile_location").attr("value")
print(f"页面标题:{page_title}")
print(f"用户资料描述:{user_profile_bio}")
print(f"用户资料公司:{user_profile_company}")
print(f"用户资料地点:{user_profile_location}")
def main(self):
email = input("email or username: ")
# 输入的密码不可见,注意密码一定不能错
password = getpass.getpass("password:")
self.login(email=email, password=password)
if __name__ == "__main__":
login = Login()
login.main()

运行效果

《模拟登陆Github》

参考资料

  • 本文参考 《Python 3 网络爬虫开发实战》 —— 10.1 模拟登陆并爬取 GitHub
  • 隐含字段参考了 《Python网络数据采集》 —— 12.3 常见表单安全措施

阅读更多

  • 字符图像识别——数字字母混合

推荐阅读
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 怀疑是每次都在新建文件,具体代码如下 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 深度学习中的Vision Transformer (ViT)详解
    本文详细介绍了深度学习中的Vision Transformer (ViT)方法。首先介绍了相关工作和ViT的基本原理,包括图像块嵌入、可学习的嵌入、位置嵌入和Transformer编码器等。接着讨论了ViT的张量维度变化、归纳偏置与混合架构、微调及更高分辨率等方面。最后给出了实验结果和相关代码的链接。本文的研究表明,对于CV任务,直接应用纯Transformer架构于图像块序列是可行的,无需依赖于卷积网络。 ... [详细]
  • 【shell】网络处理:判断IP是否在网段、两个ip是否同网段、IP地址范围、网段包含关系
    本文介绍了使用shell脚本判断IP是否在同一网段、判断IP地址是否在某个范围内、计算IP地址范围、判断网段之间的包含关系的方法和原理。通过对IP和掩码进行与计算,可以判断两个IP是否在同一网段。同时,还提供了一段用于验证IP地址的正则表达式和判断特殊IP地址的方法。 ... [详细]
  • Android日历提醒软件开源项目分享及使用教程
    本文介绍了一款名为Android日历提醒软件的开源项目,作者分享了该项目的代码和使用教程,并提供了GitHub项目地址。文章详细介绍了该软件的主界面风格、日程信息的分类查看功能,以及添加日程提醒和查看详情的界面。同时,作者还提醒了读者在使用过程中可能遇到的Android6.0权限问题,并提供了解决方法。 ... [详细]
  • 本文介绍了Windows Vista操作系统中的用户账户保护功能,该功能是为了增强系统的安全性而设计的。通过对Vista测试版的体验,可以看到系统在安全性方面的进步。该功能的引入,为用户的账户安全提供了更好的保障。 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • Python15行代码实现免费发送手机短信,推送消息「建议收藏」
    Python15行代码实现免费发 ... [详细]
  • 初始化初始化本地空版本库,仓库,英文名repositorymkdirtest&&cdtestgitinit克隆项目到本地gitclone远程同 ... [详细]
  • OWASP(安全防护、漏洞验证工具)开放式Web应用程序安全项目(OWASP,OpenWebApplicationSecurityProject)是一个组织 ... [详细]
  • mysql自动打开文件_让docker中的mysql启动时自动执行sql文件
    本文提要本文目的不仅仅是创建一个MySQL的镜像,而是在其基础上再实现启动过程中自动导入数据及数据库用户的权限设置,并且在新创建出来的容器里自动启动My ... [详细]
author-avatar
朱甜520_322
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有