Skip to content

爬虫免扫码经验分享

  • 免扫码登录
  • seleniumwire拦截请求信息

背景

关联需求

  1. 客户需要爬取某招标网站的信息,但是需要客户本人📱手机扫二维码登录。
  2. 目标信息页数非常多。考虑调用接口,但是接口调用必须在请求头中携带token。

示例:企业微信

痛点:

  1. 打开浏览器可以通过selenium解决,提供扫码界面。但是每次操作都要扫码,很麻烦,怎么解决?
  2. 在登录成功后,打开F12,可以看到响应信息中有。但是如何在程序中拿到?

相关概念:

  • selenium

img.png Selenium是一个自动化Web应用程序测试工具,它可以模拟用户在Web浏览器中的行为,例如单击、填写表单和导航等。它支持多种编程语言和浏览器,包括Chrome、Firefox、Safari和IE等。Selenium通常用于自动化测试和Web应用程序的功能测试,可以帮助开发人员和测试人员快速准确地测试Web应用程序,从而节省时间和人力成本。此外,Selenium还可以用于爬取Web数据,因为它可以模拟用户在Web浏览器中的行为来浏览网站并提取数据。

  • Cookie

Cookie是一个小的文本文件,由Web服务器发送到Web浏览器并存储在用户计算机上。它包含有关用户在网站上的活动信息,例如访问时间、页面访问次数和登录凭据等。浏览器会在随后的请求中将cookie发送回服务器,以便服务器可以识别用户并提供相关的信息或服务。Cookie通常用于跟踪用户的在线行为和个性化网站体验。

  • Token

Token是一种用于验证和授权访问的令牌,通常由服务器生成并在客户端存储。在Web开发中,通常使用Token来确保用户有权访问特定资源或执行某些操作。当用户成功登录后,服务器会生成一个Token并将其发送回客户端,在以后的请求中,客户端会在请求中包含该Token以验证身份。Token通常是加密的字符串,包含有关用户身份和访问权限的信息。常见的Token类型包括JSON Web Token (JWT)和OAuth Token。Token比传统的基于Cookie的身份验证更安全,因为它们可以避免跨站点脚本攻击(XSS攻击)和跨站点请求伪造(CSRF攻击)。

实现免扫码登录

  1. 保存cookies
  2. 植入cookies

seleniumwire

官方文档:https://pypi.org/project/selenium-wire/

工程地址:https://github.com/wkeeling/selenium-wire

Selenium Wire扩展了Selenium的Python绑定,使您能够访问浏览器发出的底层请求。您以与使用Selenium相同的方式编写代码,但是您获得了额外的api,用于检查请求和响应,并动态地对它们进行更改。 可以实现请求对象、响应对象、添加请求头、替换已存在的请求头、添加响应头、增加请求参数、在POST请求体中更新JSON等操作。

  • 工作原理

Selenium Wire的工作原理是将浏览器流量重定向到它在后台运行的内部代理服务器。当请求流经代理服务器时,它们被拦截和捕获。捕获请求可能会使事情变慢,但你可以做一些事情来限制被捕获的内容。

  • 安装

    pip install selenium-wire
    

  • 基本用法

    from seleniumwire import webdriver
    
    # 拦截request
    def interceptor_request(request):
        del request.headers['mykey']  # Remember to delete the header first
        request.headers['mykey'] = 'mykey-value'  # Spoof the referer
    
    
    # 拦截response
    def interceptor_response(request, response):
        if request.url == 'http://localhost:8088/inner/t4':
            response.headers['New-Header'] = 'Some Value'
    
    
    # 创建浏览器实例
    driver = webdriver.Chrome()
    driver.request_interceptor = interceptor_request
    driver.response_interceptor = interceptor_response
    
    # 访问首页
    driver.get('https://xxx.com')
    
    # 访问请求属性
    for request in driver.requests:
        print(request.headers)
    
        if request.response:
            print(
                request.url,
                request.response.status_code,
                request.response.headers
            )
    

参考代码

import pathlib
import time
import yaml
# from selenium import webdriver
from seleniumwire import webdriver

BASE_DIR = pathlib.Path(__file__).resolve().parent.parent
DATA_DIR = BASE_DIR / 'data'


class Wework:

    def __init__(self):
        self.driver = webdriver.Chrome()
        self.home_page = 'https://work.weixin.qq.com/wework_admin/frame'

    def save_cookie(self):
        # 访问页面
        self.driver.get(self.home_page)
        time.sleep(5)

        # 等待扫码

        # 保存cookie
        cookies = self.driver.get_cookies()
        print(cookies)
        with open(DATA_DIR / 'cookies.yaml', 'w', encoding='utf-8') as f:
            yaml.dump(cookies, f)

    def debug_login(self):
        # 拦截request
        def interceptor_request(request):
            request.headers['student'] = 'xiaofo'

        self.driver.request_interceptor = interceptor_request

        # 访问首页
        self.driver.get(self.home_page)

        # 读取本地cookie
        with open(DATA_DIR / 'cookies.yaml', 'r', encoding='utf-8') as f:
            cookies = yaml.safe_load(f)
        for cookie in cookies:
            self.driver.add_cookie(cookie)

        # 访问首页
        self.driver.get(self.home_page)
        time.sleep(5)

        for request in self.driver.requests:
            # print(request.headers)
            if request.response:
                print(request.response.headers['x-nws-log-uuid'])


if __name__ == '__main__':
    Wework().save_cookie()
    Wework().debug_login()

关于腾讯云

流程:

img.png

参考代码:

import pathlib
import time
import yaml
# from selenium import webdriver
from seleniumwire import webdriver

BASE_DIR = pathlib.Path(__file__).resolve().parent.parent
DATA_DIR = BASE_DIR / 'data'


class Wework:

    def __init__(self):
        self.driver = webdriver.Chrome()
        self.driver.implicitly_wait(3)
        self.login_page = 'https://cloud.tencent.com/login?s_url=https%3A%2F%2Fcloud.tencent.com%2F'
        self.product_page = 'https://cloud.tencent.com/product'

    def save_cookie(self):
        # 访问页面
        self.driver.get(self.login_page)
        time.sleep(10)

        # 等待扫码

        # 保存cookie
        cookies = self.driver.get_cookies()
        print(cookies)
        with open(DATA_DIR / 'cookies.yaml', 'w', encoding='utf-8') as f:
            yaml.dump(cookies, f)

    def debug_login(self):

        # 访问产品页面
        self.driver.get(self.product_page)

        # 读取本地cookie
        with open(DATA_DIR / 'cookies.yaml', 'r', encoding='utf-8') as f:
            cookies = yaml.safe_load(f)
        for cookie in cookies:
            self.driver.add_cookie(cookie)

        # 再次访问云产品页面(停留,确保登录身份正常)
        self.driver.get(self.product_page)
        self.driver.refresh()
        time.sleep(3)

        self.driver.get('https://console.cloud.tencent.com/')
        time.sleep(5)

if __name__ == '__main__':
    # Wework().save_cookie()
    Wework().debug_login()