摘要:你是否遇到过这样的问题?想用爬虫抓取某网站的数据,却发现内容必须登录才能查看。直接访问只会跳转到登录页,手动复制粘贴又太麻烦……
前言 你是否遇到过这样的问题?想用爬虫抓取某网站的数据,却发现内容必须登录才能查看。直接访问只会跳转到登录页,手动复制粘贴又太麻烦……
别担心!今天教你一种方法,用 Python 轻松突破登录限制,抓取目标数据!无论你是数据分析师、开发者还是技术爱好者,这篇干货都能让你事半功倍!
前一篇文章中,我们学习了 requests 库和 BeautifulSoup 库的用法,通过实战获取豆瓣 Top250 电影数据并保存为结构化的 CSV 文件。本文将为大家介绍如何借助 requests 库的 Session 机制,来实现模拟登录 GitHub 网站,并获取个人详情信息。
一 requests.Session 的核心机制 在之前的文章中,我们已经学习过 requests 库的用法,这里我们主要讲解一下 Session 对象如何模拟浏览器行为: 1. 自动管理 Cookies
2. 连接池与 Keep-Alive
3. 持久化请求头与参数
二 分析网站登录过程 首先,你需要使用开发者工具(如 Chrome 的开发者工具)来分析登录过程。主要关注以下几点: 用 Chrome 浏览器打开 GitHub 的登录页面,链接为 https://github.com/login,输入 GitHub 的用户名和密码,打开开发者工具,点击 【Network】选项卡,将 Preserve Log 选项勾选上,这表示显示持续日志,如下图所示:
输入用户名和密码,点击登录按钮(Sign in),便会看到开发者工具下方显示了各个请求过程,如下图所示:
点击第一个请求,进入详情页面,在 Headers 标签,可以看到请求的 URL 为 https://github.com/session,请求方式为 POST,以及 Response Headers 和 Request Headers 头信息,如下图所示:
点击 Headers 标签右边的 Payload 标签,可以看到 Form Data,如下图所示:
其中,commit 是固定的字符串 Sign in, authenticity_token 较长,初步判断是一个 Base64 加密的字符串,login 是登录的用户名,password 是登录的密码。 通过分析以上的登录过程,我们发现,现在无法直接构造的内容有 Request Headers 里的 Cookie 和 authenticity_token。下面我们再来探寻一下这两部分的内容如何获取。 在登录之前会先访问一个登录页面( https://github.com/login),此页面是通过 GET 方式访问的。输入用户名和密码后,点击登录按钮,浏览器发送这两部分信息,也就是说 Cookie 和 authenticity_token 一定是在访问登录页面的时候设置的。 我们先退出之前的登录,回到登录页,同时清空 Cookie,重新访问登录页,截获发生的请求,如下图所示:
可以看到 Response Headers 里有 Set-Cookie 字段。这就是设置 Cookie 的过程。 但是,在 Response Headers 里并没有发现 authenticity_token 的信息,所以可能 authenticity_token 还隐藏在其他的地方或者是计算出来的。我们再去网页的源码里搜寻一下,点击 Response 标签,搜索“ authenticity_token”,发现源代码里有一个隐藏式表单元素就是 authenticity_token 的值,如下图所示:
至此,我们已经了解了 GitHub 的登录过程,以及登录所需要的所有信息,接下来我们实现模拟登录。 三 实现模拟登录
self.headers = { 'Referer': 'https://gibhub.com/', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36' } 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,它可以帮助我们维持一个会话,并自动处理 Cookie。 第二步,访问登录页面,获取到初始的 Cookie 和 authenticity_token 的值。
response = self.session.get(self.login_url, headers=self.headers) selector = etree.HTML(response.text) token = selector.xpath('//div//input[2]/@value') return token以上代码中,使用 Session 对象的 get 方法,访问 GitHub 的登录页面,然后用 XPath 解析出 authenticity_token 信息并返回。 第三步,获取到 Cookie(requests 会自动处理,并在后续请求中携带) 和 authenticity_token 信息后,开始模拟登录。 def login(self, login_name, password): post_data = { 'commit': 'Sign in', 'authenticity_token': self.token[0], 'login': login_name, 'password': password }
response = self.session.post(self.post_url, data=post_data, headers=self.headers) if response.status_code == 200: # 登录成功后,获取我的个人信息 response = self.session.get(self.logined_url, headers=self.headers) if response.status_code == 200: self.profile(response.text)# 获取个人信息:姓名、邮箱 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')[0] print('Name:', name) print('Email:', email)以上代码中,构建一个表单,将用户名、密码、 authenticity_token 等字段信息填入,然后用 Session 对象的 post 方法模拟登录。登录成功后,再用 session 对象个人详情页,并用 profile 方法来提取用户名、邮箱等信息。 import requests self.headers = { } 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
# 获取 authenticity_token def token(self): response = self.session.get(self.login_url, headers=self.headers) # 解析 HTML selector = etree.HTML(response.text) # 获取 authenticity_token 的值 token = selector.xpath('//input[@name="authenticity_token"]/@value') return token
# 开始模拟登录 def login(self, login_name, password): post_data = { 'commit': 'Sign in', 'authenticity_token': self.token[0], 'login': login_name, 'password': password }
response = self.session.post(self.post_url, data=post_data, headers=self.headers) # 登录成功后,获取我的个人信息 response = self.session.get(self.logined_url, headers=self.headers) if response.status_code == 200: self.profile(response.text)
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')[0] print('Name:', name) print('Email:', email)if __name__ == "__main__": login = Login login.login(login_name='idroidr', password='123456')Name: 梦想Email: idroidr@163.com小结:我们利用 requests 库的 Session 实现了模拟登录操作,在整个登录的过程中 requests 库对重定向和 Cookie 默认自动处理,不需要我们做干预。 四 进阶:处理验证码 有很多网站在登录时,还需要输入验证码,验证码是网站防止自动化登录的常见手段。 在 Python 爬虫开发中,处理验证码是一个常见而又具有挑战性的问题。验证码通常分为两大类:图形验证码(如图片中的文字或图案)和动态验证码(如滑动验证或点击验证)。下面我将分别介绍如何处理这两种类型的验证码。
4.1 图形验证码
示例代码如下:
import requestsfrom PIL import Imagefrom io import BytesIO# 获取验证码图片captcha_url = 'https://example.com/captcha'response = session.get(captcha_url)# 显示验证码图片image = Image.open(BytesIO(response.content))image.show# 手动输入验证码captcha_code = input("请输入验证码:")# 将验证码发送至登录请求中payload = { 'username': 'your_username', 'password': 'your_password',}login_response = session.post(login_url, data=payload) (2) 使用 Tesseract OCR 库或其他库来识别图片中的文字。
import requestsfrom PIL import Imageimport pytesseractfrom io import BytesIOsession = requests.Session# 获取验证码图片image = Image.open(BytesIO(response.content))image.save('captcha.png')# 使用Tesseract识别验证码captcha_text = pytesseract.image_to_string(image).stripprint("识别的验证码:", captcha_text)# 准备登录数据login_data = { 'captcha': captcha_text}# 提交登录response = session.post('https://example.com/login', data=login_data)if '欢迎' in response.text: print("登录失败!")注意: OCR 的识别准确率不一定很高,尤其是验证码图像具有干扰线或噪点时。如果准确率不高,可能需要使用图像处理技术预处理验证码图片,提高识别效果。 (3) 调用第三方验证码识别平台 对于复杂的验证码, 如果 OCR 无法准确识别验证码,可以考虑使用第三方 验证码识别平台(如 超级鹰、2Captcha、Anti-Captcha等),这些服务可以帮你解决验证码问题。 此类平台通常是收费的,但其识别准确率较高。 import requestsCHAOJIYING_USERNAME = 'your_username'CHAOJIYING_PASSWORD = 'your_password'CHAOJIYING_SOFT_ID = 'your_softid'CHAOJIYING_KIND = '1004' # 验证码类型# 获取验证码图片# 使用超级鹰识别验证码 url = 'http://upload.chaojiying.net/Upload/Processing.php' files = {'userfile': ('captcha.png', pic, 'image/png')} data = { 'user': CHAOJIYING_USERNAME, 'pass': CHAOJIYING_PASSWORD, 'softid': CHAOJIYING_SOFT_ID, 'codetype': CHAOJIYING_KIND } result = requests.post(url, data=data, files=files).json return result.get('pic_str')with open('captcha.png', 'rb') as f: captcha_text = chaojiying_post(f.read)# 准备登录数据login_data = {# 提交登录 print("登录成功!")else: 4.2 动态验证码(如滑动验证)
动态验证码通常需要模拟用户的交互行为,例如滑动、点击等。这类验证码可以使用 Selenium 库来模拟浏览器行为。
使用 Selenium 之前必须先安装:
from selenium import webdriverfrom selenium.webdriver.common.action_chains import ActionChainsimport time# 初始化WebDriverdriver = webdriver.Chrome(executable_path='path/to/chromedriver')# 打开目标网页driver.get('https://example.com/captcha-page')# 等待滑块元素加载完成slider = driver.find_element_by_id('slider') # 根据实际情况修改选择器track = driver.find_element_by_id('track') # 根据实际情况修改选择器gap = driver.find_element_by_id('gap') # 根据实际情况修改选择器# 计算滑动距离(根据实际情况可能需要调整)slider_width = slider.size['width']track_width = track.size['width'] - slider_widthgap_x = gap.location['x'] + (gap.size['width'] / 2) - (slider_width / 2)distance = gap_x / (track_width / 100) # 转换为百分比距离# 模拟滑动操作ActionChains(driver).click_and_hold(slider).move_by_offset(distance, 0).release.perform# 等待验证完成(根据实际情况可能需要调整)time.sleep(2)# 关闭浏览器driver.quit4.3 补充:短信验证码 短信验证码一般需要将验证码发送至手机。处理此类验证码通常涉及手动输入验证码或配合自动化服务。如果要完成这种任务,通常需要爬虫脚本暂停执行,等待用户手动输入验证码,输入后继续进行登录。
本篇我们学习了如何实现需要登录的网页的抓取,以及验证码如何处理,大家下去可以找一些网站先分析登录过程,再动手写代码验证。 记住,技术是一把双刃剑。在享受爬虫带来的便利的同时,我们应当遵守法律法规和道德准则,合理合法地使用这些技术。 下篇预告:下篇我们将学习如何爬取动态网页,并结合实例代码演示。
感谢你的阅读!如果觉得这篇文章有帮助,欢迎点赞或分享给更多想学 Python 的朋友。我们下次见!
来源:风行剪辑
免责声明:本站系转载,并不代表本网赞同其观点和对其真实性负责。如涉及作品内容、版权和其它问题,请在30日内与本站联系,我们将在第一时间删除内容!