用mitmproxy替代selenium-wire
做爬虫的人应该都知道selenium-wire,这是一个浏览器流量的抓取工具,这个工具2022年10月15日后已经停止维护了,它的本质是对mitmproxy的封装,由于它采取了内置mitmproxy的方式,不会随着mitmproxy的升级而升级,由于代码陈旧现在基本上已经无法使用了。我曾经改过一版selenium-wire,把内置的mitmproxy改成外置,这样就可以使用最新版mitmproxy了,代码如下:
selenium-wire
由于selenium-wire只是mitmproxy的一个封装,建议直接使用mitmproxy更好。下面是我写的简单封装:
import os
from selenium.webdriver.common.by import By
# import proxy as webdriver
from selenium import webdriver
# from seleniumwire.utils import decode
import time
import shutil
from selenium.webdriver.common.proxy import Proxy, ProxyType
from selenium.webdriver.common.actions import mouse_button
from model.CrawlerModel.repository import Repository
import subprocess
from multiprocessing import Process, Value
import requests
from mitmproxy import http
from mitmproxy import ctx
import threading
from mitmproxy import options
from mitmproxy.tools import dump
import asyncio
import config
import randomclass PServer:def __init__(self,profile):self.ready = threading.Event()self.port = profile.getPort()def running(self):self.ready.set()async def backend(self,host, port):self.ready.clear()self.options = opts = options.Options(# mode=[f"upstream:{proxy}"],# upstream_auth=config.proxy[self.addon.retries]['auth'],# connection_strategy='lazy',# keep_alive_timeout=500,# http2_ping_keepalive=0,listen_host=host,listen_port=port,ssl_insecure=True # 如果没有这行,有些网站会出错unsafe legacy renegotiation disabled,比如:https://money.smt.docomo.ne.jp/contents/creditcard-good-to-have)# opts.add_option("connection_strategy", str, "eager", "Connection strategy (eager|lazy)")# opts.update(connection_strategy="lazy")self.master = master = dump.DumpMaster(opts,# with_termlog=True,with_termlog=False,with_dumper=False,)master.addons.add(self)master.addons.add(self.addon)await master.run()return masterdef run(self):asyncio.run(self.backend('127.0.0.1', self.port))def start(self,addon):self.addon=addonself.thread = threading.Thread(name='Proxy Server', target=self.run)# t.daemon = not options.get('standalone')self.thread.start()# 等待proxy工作,如果超过30秒就报错if not self.ready.wait(30):raise Exception('proxy timeout')# asyncio.wait(self.ready)# time.sleep(5)def stopServer(self):ctx.options.update(server=False)def shutdown(self):ctx.master.event_loop.call_soon_threadsafe(self.stopServer)ctx.master.shutdown()self.thread.join()
selenium中使用下面代码设置代理:
proxyServer=PServer(profile)options.add_argument(f'--proxy-server=127.0.0.1:{str(profile.getPort())}')
抓取流量的时候使用下面代码:
def response(self,flow: http.HTTPFlow) -> None:request=flow.requestresponse=flow.responseself.requests.remove(flow.request)。。。proxyServer.start(self)
profile是自己写的管理端口的类,可以忽略。proxyServer.start(self)的意图是在当前类中寻找response方法。当然还有其他方法,详细参照mitmproxy文档。
由于详细解释比较麻烦,写的粗糙一点。