【自動化】使用PlayWright+代理IP實現多環境隔離

来源:https://www.cnblogs.com/kylexy/p/18051812
-Advertisement-
Play Games

Playwright是由微軟公司2020年初發佈的新一代自動化測試工具,相較於目前最常用的Selenium,它僅用一個API即可自動執行Chromium、Firefox、WebKit等主流瀏覽器自動化操作。 對各種開發語言也有非常好的支持。常用的NodeJs、Java、python都有支持,且有豐富 ...


Playwright是由微軟公司2020年初發佈的新一代自動化測試工具,相較於目前最常用的Selenium,它僅用一個API即可自動執行Chromium、Firefox、WebKit等主流瀏覽器自動化操作。

對各種開發語言也有非常好的支持。常用的NodeJs、Java、python都有支持,且有豐富的文檔參考。

Python環境下的安裝使用

1、安裝依賴庫
pip install playwright

2、安裝瀏覽器驅動文件
安裝好依賴庫之後,會自動註冊全局命令。下麵2種方式都可以快速安裝驅動文件(驅動就是內置的瀏覽器)
python -m playwright install
或者:
playwright install

如果命令是python3,替換為pip3 install 和python3 -m 即可。

網上有非常多的教程。安裝並非本文的重點。

多環境隔離的應用場景

常見的如爬蟲,可能需要使用代理IP隔離開不同的瀏覽器進行數據抓取。

像另一些需要多號操作的營銷內容,也需要多個瀏覽器互相隔離開。更高要求的才會使用代理+隔離的方式。

產生完全不一樣的瀏覽器環境。比如大量的號去做不同的事。

還有很多常用的場景。獨立乾凈的瀏覽器環境+Playwright的自動化。可以實現非常多的有趣的應用。

Playwright啟動瀏覽器有幾種模式。我們需要先進行瞭解。

1、普通的無痕模式,用完即銷毀。這種方式下,瀏覽器的歷史記錄之類的不會保存。適合用於爬蟲性的工作。

代碼大致是這樣的。

browser = pw.chromium.launch(headless=headless, proxy=my_proxy,
                                         ignore_default_args=ignore_args,
                                 args=default_args)

browserContext = browser.new_context(user_agent=userAgent, storage_state=storage_state)

可以指定UserAgent,這是我們模擬不同操作系統和瀏覽器數據的必填項。
也可以指定headless無頭模式,這樣瀏覽器不會有界面出現。背後去工作。

2、普通的持久模式,需要指定用戶的數據目錄。實現數據的隔離。
比如1號瀏覽器存到data1,2號存到data2,數據不會衝突,各乾各的事,可以同時登陸一個網站的多個賬號,互不影響。

不方便的地方在於,每次執行完任務,瀏覽器會隨著程式關閉而關閉。

copy一段網上的示例

# 獲取 google chrome 的本地緩存文件
USER_DIR_PATH = f"C:\\Users\\{getpass.getuser()}\\AppData\Local\Google\Chrome\\User Data"

with sync_playwright() as p:
    browser = p.chromium.launch_persistent_context(
                        # 指定本機用戶緩存地址,這是隔離環境的主要點,指定不同的目錄存放用戶的數據。
                        user_data_dir=USER_DIR_PATH,
                        # 接收下載事件,允許下載需要
                        accept_downloads=True,
                        # 設置 GUI 模式,可以看到瀏覽器界面
                        headless=False,
                        bypass_csp=True,
                        slow_mo=1000,
                        channel="chrome",
                    )

    page = browser.new_page()
    page.goto("https://www.cnblogs.com/yoyoketang")

    page.pause()

3、直連繫統的Chrome。如果系統有Chrome瀏覽器,playwright可以直接連接,併進行操作。但是需要做一些配置。

這也是我目前用得最多的模式。

核心的原理就是使用CDP連接上Chrome。需要開啟Chrome時,指定一個調試埠,供我們遠程連接上去使用。

官方提供的具體函數是
pw.chromium.connect_over_cdp(cdp_url, timeout=0)

優點在於:
腳本和瀏覽器分離。腳本開不開,瀏覽器都不影響。只是需要自動化的時候,腳本才去工作。

缺點:
就是配置略麻煩。好在封裝好之後,就是一次的麻煩,後面也會比較順暢。

如何封裝屬於自己的快速啟動類,python和java都可以,下次再聊。

下麵以Chrome瀏覽器+動態代理為例構建多個不同的環境

由於Chrome自帶的proxy 代理功能並不支持帶賬號密碼的代理方式。
而我們採購的代理,肯定都是有賬號密碼的。

所以核心點是添加一個插件,配置上代理,能支持http和socks5的代理,並支持賬號密碼進行連接。

然後再通過python,調用系統的瀏覽器,產生不同的環境,使用不同的代理IP。就能達到目標。

直接上圖
file

沒有好用的收費代理,本地模擬了一個HK節點的代理。

可以看到4個瀏覽器的指紋已經不一樣了。配合上代理,就是乾凈的環境了。

核心的邏輯在於啟用不同的DataDir用戶數據目錄,加個獨立的代理插件來支持http和socks5的代理,

1、核心1,使用python來快速啟動Chrome

if sys.platform.startswith('linux'):  # Linux
    exe_name = 'chrome'
    extParam.append('--no-sandbox')
elif sys.platform.startswith('win'):  # Windows
    win_path = 'C:\Program Files\Google\Chrome\Application\chrome.exe'
    exe_name = win_path if os.path.exists(win_path) else 'chrome.exe'
elif sys.platform.startswith('darwin'):  # Mac
    exe_name = '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome'
    extParam.append('--no-sandbox')

# 啟用UA
if config.get('user_agent'):
    extParam.append(fr'--user-agent="{config.get("user_agent")}"')

# 啟用無痕
if config.get('incognito'):
    extParam.append('--incognito')

# 無開屏
if config.get('no_window'):
    extParam.append('--no-startup-window')
        
command = fr'"{exe_name}" --remote-debugging-port={port} --user-data-dir="{data_dir}" --no-sandbox --disable-gpu --disable-software-rasterize --disable-background-networking --disable-background-mode --disable-sync --disable-blink-features=AutomationControlled --disable-client-side-phishing-detection --disable-default-apps --disable-desktop-notifications --disable-hang-monitor --disable-infobars --disable-notifications --disable-plugins-discovery --no-first-run --dns-prefetch-disable --ignore-certificate-errors --allow-running-insecure-content --test-type --origin-trial-disabled-features=WebGPU --no-default-browser-check --no-service-autorun --disable-popup-blocking --password-store=basic --disable-web-security --disable-dev-shm-usage --disable-component-update --disable-features=RendererCodeIntegrity --disable-features=FlashDeprecationWarning,EnablePasswordsAccountStorage {" ".join(extParam)}'

os.popen(command)

還有不少代碼,就不往上面貼了。

2、核心點2,動態載入插件進不同的Chrome環境,各用各的代理。

def create_proxyauth_extension(proxy_host, proxy_port,
                               proxy_username, proxy_password,
                               scheme='http', plugin_dir=None):
    """
    代理認證插件,返回代理插件的地址
    Chrome使用帶賬號密碼的代理IP
    插件來源:https://github.com/henices/Chrome-proxy-helper
    參考:https://ask.hellobi.com/blog/cuiqingcai/10307#articleHeader5
    https://my.oschina.net/sunboy2050/blog/1858508
    https://github.com/aneasystone/selenium-test/blob/master/08-proxy-with-password.py
    https://developer.chrome.com/extensions/proxy
    args:
        proxy_host (str): 你的代理地址或者功能變數名稱(str類型)
        proxy_port (int): 代理埠號(int類型)
        proxy_username (str):用戶名(字元串)
        proxy_password (str): 密碼 (字元串)
    kwargs:
        scheme (str): 代理方式 預設http
        plugin_dir (str): 擴展的目錄路徑

    return str -> plugin_path
    """

    # 插件目錄
    if not plugin_dir:
        plugin_dir = os.path.join(get_data_dir('chrome_plugin'), f'custom_proxyauth_plugin')
    if not os.path.exists(plugin_dir):
        os.makedirs(plugin_dir)

    # 生成的Zip文件地址
    plugin_file = os.path.join(plugin_dir, f"proxy_plugin_{proxy_host}_{proxy_port}.zip")
    # 舊文件清理掉
    if os.path.exists(plugin_file):
        os.remove(plugin_file)

    manifest_json = """
    {
        "version": "1.0.0",
        "manifest_version": 2,
        "name": "Chrome Proxy",
        "permissions": [
            "proxy",
            "tabs",
            "unlimitedStorage",
            "storage",
            "<all_urls>",
            "webRequest",
            "webRequestBlocking"
        ],
        "background": {
            "scripts": ["background.js"]
        },
        "minimum_chrome_version":"22.0.0"
    }
    """

    background_js = string.Template(
        """
        var config = {
                mode: "fixed_servers",
                pacScript: {},
                rules: {
                  singleProxy: {
                    scheme: "${scheme}",
                    host: "${host}",
                    port: ${port}
                  },
                  bypassList: ["foobar.com"]
                }
              };

        chrome.proxy.settings.set({value: config, scope: "regular"}, function() {});

        function callbackFn(details) {
            return {
                authCredentials: {
                    username: "${username}",
                    password: "${password}"
                }
            };
        }

        chrome.webRequest.onAuthRequired.addListener(
                    callbackFn,
                    {urls: ["<all_urls>"]},
                    ['blocking']
        );
        """
    ).substitute(
        host=proxy_host,
        port=proxy_port,
        username=proxy_username,
        password=proxy_password,
        scheme=scheme,
    )

    # 先寫ZIP
    with zipfile.ZipFile(plugin_file, 'w') as zp:
        zp.writestr("manifest.json", manifest_json)
        zp.writestr("background.js", background_js)

    # 再手寫文件過去
    with open(os.path.join(plugin_dir, 'manifest.json'), 'w+') as fi:
        fi.write(manifest_json)

    with open(os.path.join(plugin_dir, 'background.js'), 'w+') as fi:
        fi.write(background_js)

    return plugin_file

Java也可以用同樣的方式實現。後續配上Java的多線程。相信開100個視窗幹活,不是什麼難事。

Playwright在下載上傳方面,比以前的Selenium要強很多。還有很多功能,下次再分享。

關註我的公眾號:青塬科技,定期分享經驗文章。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • C++ MySQL資料庫連接池 新手學了C++多線程,看了些資料練手寫了C++資料庫連接池小項目,自己的源碼地址 關鍵技術點 MySQL資料庫編程、單例模式、queue隊列容器、C++11多線程編程、線程互斥、線程同步通信和 unique_lock、基於CAS的原子整形、智能指針shared_ptr ...
  • 數據過濾在數據分析過程中具有極其重要的地位,因為在真實世界的數據集中,往往存在重覆、缺失或異常的數據。pandas提供的數據過濾功能可以幫助我們輕鬆地識別和處理這些問題數據,從而確保數據的質量和準確性。 今天介紹的query函數,為我們提供了強大靈活的數據過濾方式,有助於從複雜的數據集中提取有價值的 ...
  • 目錄數組(Array)一、數組概念二、如何聲明一個數組三、如何為數組初始化1、數組本身初始化:2、數組的元素初始化2.1 一維數組2.2多維數組四、如何表示數組的各個概念五、數組記憶體和分配空間六、數組相關演算法七、十大內部排序演算法八、數組的工具類:Arrays九、數組的異常 數組(Array) 一、數 ...
  • 前言 在學習C++時,const關鍵字的知識點分散在書的各個章節。當我們嘗試在編程時使用const時,總會感覺有一些細節被遺忘,因而不能得心應手地使用const關鍵字。因此,本篇文章嘗試著對const關鍵字的做一些總結。參考書籍《C++ Primer Plus》 const總結 這裡是我做的關於co ...
  • 在Spring中,實例化Bean對象涉及構造方法的調用。通過分析源碼,我們瞭解到實例化的步驟和推斷構造方法的過程。當一個類只有一個構造方法時,Spring會根據具體情況決定是否使用該構造方法。如果一個類存在多個構造方法,就需要根據具體情況具體分析。 ...
  • polymorphism 靜態聯編和動態聯編 多態性(polymorphism)提供介面與具體實現之間的另一層隔離,從而將”what”和”how”分離開來。多態性改善了代碼的可讀性和組織性,同時也使創建的程式具有可擴展性,項目不僅在最初創建時期可以擴展,而且當項目在需要有新的功能時也能擴展。 c++ ...
  • 一、簡介 在 Java 多線程編程中,還有一個非常重要的設計模式,它就是:生產者和消費者模型。 這種模型可以充分發揮 cpu 的多線程特性,通過一些平衡手段能有效的提升系統整體處理數據的速度,減輕系統負載,提高程式的效率和穩定性,同時實現模塊之間的解耦。 那什麼是生產者和消費者模型呢? 簡單的說,生 ...
  • 下拉列表(下拉框)可以確保用戶僅從預先給定的選項中進行選擇,這樣不僅能減少數據輸入錯誤,還能節省時間提高效率。在MS Excel中,我們可以通過 “數據驗證” 提供的選項來創建下拉列表,但如果要在Java程式中通過代碼實現這一功能,可能需要藉助一些第三方庫。本文將分享兩種使用免費Java庫在Exce ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...