數(shù)據(jù)抓取實(shí)戰(zhàn)(一)

概述

在web開發(fā)境析,測試以及性能優(yōu)化,數(shù)據(jù)抓包時(shí),常會(huì)借助一此工具翼岁,幫助我們更好地理解和控制網(wǎng)絡(luò)通信過程。

本文提供兩個(gè)工具FiddlerCoreTitaniumProxy的實(shí)現(xiàn)方式以及示例代碼司光,分享幾個(gè)數(shù)據(jù)抓包的實(shí)際案例琅坡,供大家參考。

FiddlerCore

簡介

FiddlerCore是一個(gè)強(qiáng)大的庫残家,允許你使用C#攔截榆俺、修改HTTP(Https)和WebSocket流量。

它主要有以下一些特點(diǎn)和功能:

  • 網(wǎng)絡(luò)抓包:可以捕獲瀏覽器與服務(wù)器之間的 HTTP/HTTPS 請求和響應(yīng)坞淮。

  • 請求分析:詳細(xì)查看請求的各種信息茴晋,如請求頭、請求體回窘、響應(yīng)頭诺擅、響應(yīng)體等。

  • 模擬請求:能夠手動(dòng)創(chuàng)建和發(fā)送自定義請求啡直。

  • 調(diào)試會(huì)話:方便對網(wǎng)絡(luò)交互進(jìn)行故障排查和調(diào)試烁涌。

  • 篡改請求和響應(yīng):在測試和開發(fā)中可臨時(shí)修改數(shù)據(jù)。

Fiddlercore攔截Https的原理是自己創(chuàng)建一個(gè)Https的證書酒觅,重新對網(wǎng)站的鏈接數(shù)據(jù)進(jìn)行加密傳輸撮执,所以,我們要通過代碼創(chuàng)建一個(gè)https證書給Fiddlercore舷丹。

https的處理過程需要一個(gè)自簽名證書:

fiddler.png

創(chuàng)建Https證書有兩種方式抒钱,一種是通過MakeCert.exe ,另一種是通過 CertMaker.dll及BCMakeCert.dll來創(chuàng)建。

在官網(wǎng)說明中谋币,明確的說了兩點(diǎn):

1仗扬、MakeCert.exe使用Windows API生成存儲(chǔ)在用戶的\Personal\Certificates存儲(chǔ)中的證書。這些證書與iOS設(shè)備不兼容瑞信,后者需要證書中未由MakeCert.exe設(shè)置的特定字段厉颤。
2、CertMaker.dll使用BouncyCastle C#庫(BCMakeCert.dll)從頭開始生成新證書凡简。這些證書僅存儲(chǔ)在內(nèi)存中逼友,并與iOS設(shè)備兼容。

我們 在Fiddlercore編程的時(shí)候秤涩,通常采用dll方式創(chuàng)建證書帜乞,創(chuàng)建后的證書放在內(nèi)存中。所以筐眷,僅當(dāng)程序第一次啟動(dòng)的時(shí)候黎烈,我們才需要?jiǎng)?chuàng)建證書,以后再啟動(dòng)程序匀谣,就不需要?jiǎng)?chuàng)建證書了照棋,這個(gè)過程持續(xù)到電腦重啟為止。

FiddlerCoreStartupSettingsBuilder的配置方法如下:

常用設(shè)置包括:

·ListenOnPort(int):指定FiddlerCore將偵聽的端口武翎。若設(shè)置為0烈炭,則表示隨機(jī)分配端口。

·AllowRemoteClients():允許FiddlerCore接受來自當(dāng)前機(jī)器外部的請求宝恶,例如遠(yuǎn)程計(jì)算機(jī)和設(shè)備符隙。在允許遠(yuǎn)程客戶端連接到FiddlerCore時(shí)需謹(jǐn)慎,因?yàn)楣粽呖赡芡ㄟ^該FiddlerCore實(shí)例代理其流量垫毙,從而繞過IPSec流量規(guī)則和內(nèi)部網(wǎng)防火墻霹疫。系統(tǒng)代理設(shè)置方面,有多種可能需要修改以適應(yīng)合適代理設(shè)置的系統(tǒng)和連接類型综芥,在此只處理最常見場景丽蝎。對于更高級的代理配置,請參閱注冊為系統(tǒng)代理文章膀藐。

RegisterAsSystemProxy()可修改本地局域網(wǎng)連接的代理設(shè)置屠阻,使其指向FiddlerCore在本地主機(jī)上監(jiān)聽的端口。

MonitorAllConnections()可修改所有系統(tǒng)連接的代理設(shè)置消请,使其指向FiddlerCore在本地主機(jī)上偵聽的端口。

CaptureFTP()可修改系統(tǒng)中與ftp相關(guān)聯(lián)的代理設(shè)置类腮,使其指向FiddlerCore在本地主機(jī)上偵聽的端口臊泰。HookUsingPACFile()可修改當(dāng)前使用PAC文件配置方式進(jìn)行網(wǎng)絡(luò)連接時(shí)所使用到的代理設(shè)置。同時(shí)蚜枢,F(xiàn)iddlerCore還提供了一個(gè)PAC文件用于調(diào)整網(wǎng)絡(luò)連接缸逃,在服務(wù)默認(rèn)PAC文件時(shí)可以通過更改“fiddler.proxy.pacfile”進(jìn)行配置右蹦,默認(rèn)情況下它包含了FindProxyForURL(url, host)函數(shù)體等內(nèi)容:"

FiddlerCore 是一個(gè) .NET 類庫舍败,沒有界面,您可以將其集成到您的 .NET 應(yīng)用程序中。它提供 .NETCore、.NET Framework版本挖腰,官方收費(fèi),我提供了一個(gè)免費(fèi)版本5.0.2忙干,直接在項(xiàng)目中使用辕翰。

以下以.netcore版本為例,FiddlerCore5.0.2版本 項(xiàng)目中引用FiddlerCore

安裝證書

//加v runsoft1024提供源碼
static bool InstallCertificate()
{
    FiddlerApplication.Log.LogString($"安裝證書,為了監(jiān)聽https請求");
    if (!CertMaker.rootCertExists())
    {
        if (!CertMaker.createRootCert())
            return false;

        if (!CertMaker.trustRootCert())
            return false;
    }

    return true;
}

卸載證書

static bool UninstallCertificate()
{
    if (CertMaker.rootCertExists())
    {
        if (!CertMaker.removeFiddlerGeneratedCerts(true))
            return false;
    }
    return true;
}

創(chuàng)建代理

static void StartupFiddler()
{
    // Attach to events of interest:
    FiddlerApplication.AfterSessionComplete += session => Console.WriteLine(session.fullUrl);
    //Build startup settings:
    var settings = new FiddlerCoreStartupSettingsBuilder()
        .ListenOnPort(9898)
        .RegisterAsSystemProxy()
        .DecryptSSL()
        .OptimizeThreadPool()  //啟用多線程
        .AllowRemoteClients()  //websocket open
        .Build();

    CONFIG.EnableIPv6 = true; //websocket open
    CONFIG.IgnoreServerCertErrors = true;
   
    // Start:
    FiddlerApplication.Startup(settings);
    FiddlerApplication.Log.LogString($"Created endpoint listening on port {CONFIG.ListenPort}");  
}

關(guān)閉代理

static void UninstallFiddler()
{
    if (FiddlerApplication.IsStarted())
    {
        FiddlerApplication.Shutdown();
    }
}

處理事件

//攔截請求與響應(yīng)事件
static void AttachListening()
{
    //FiddlerApplication.OnNotification += (o, nea) => Console.WriteLine($"** NotifyUser: {nea.NotifyString}");
    FiddlerApplication.Log.OnLogString += (o, lea) => Console.WriteLine($"** LogString: {lea.LogString}");
    FiddlerApplication.OnWebSocketMessage += FiddlerApplication_OnWebSocketMessage;
    FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
    FiddlerApplication.BeforeResponse += FiddlerApplication_BeforeResponse;
}

websocket處理

FiddlerApplication.OnWebSocketMessage += FiddlerApplication_OnWebSocketMessage;
static void FiddlerApplication_OnWebSocketMessage(object? sender, WebSocketMessageEventArgs e)
{
    //編寫業(yè)務(wù)邏輯
    var payload = e.oWSM.PayloadAsBytes();
    var txt = Utilities.ByteArrayToString(payload);
    var s = e.oWSM.PayloadAsString();
    e.oWSM.SetPayload(payload);
}

http請求事件

FiddlerApplication.BeforeRequest += FiddlerApplication_BeforeRequest;
static void FiddlerApplication_BeforeRequest(Session oSession)
{
    //為了啟用響應(yīng)篡改,緩沖模式必須被啟用挪丢;
    //這允許FiddlerCore允許修改BeforeResponse處理程序中的響應(yīng),而不是流式傳輸響應(yīng)進(jìn)來時(shí)對客戶端的響應(yīng)蹂风。
    oSession.bBufferResponse = false;

    //只監(jiān)聽目標(biāo)網(wǎng)站
    if(!oSession.fullUrl.Contains("rscode.cn"))
    {
        return;
    }
    // 如果您希望FiddlerCore通過以下方式自動(dòng)進(jìn)行身份驗(yàn)證,請?jiān)O(shè)置此屬性
    // answering Digest/Negotiate/NTLM/Kerberos challenges itself
    //session["X-AutoAuth"] = "(default)";

    Console.ForegroundColor = ConsoleColor.Green;
    Console.WriteLine(String.Format("{0} {1}", oSession.RequestMethod, oSession.fullUrl));
    
    //header
    Console.ForegroundColor = ConsoleColor.White;
    for (int i = 0; i < oSession.RequestHeaders.Count(); i++)
    {
        var s=String.Format("{0,-20}{1}", oSession.RequestHeaders[i].Name, oSession.RequestHeaders[i].Value);
        FiddlerApplication.Log.LogString($" {s}");
    }
    
    //body
    if(oSession.RequestBody!=null)
    {
       // var s= Encoding.UTF8.GetString(oSession.RequestBody);
        var s=oSession.GetRequestBodyAsString();
        FiddlerApplication.Log.LogString($" {s}");
    }
}

http響應(yīng)事件

FiddlerApplication.BeforeResponse += FiddlerApplication_BeforeResponse;
/// <summary>攔截請求返回Response信息</summary>
static void FiddlerApplication_BeforeResponse(Session oSession)
{
    //只監(jiān)聽目標(biāo)網(wǎng)站
    if (!oSession.oRequest.host.Contains("rscode.cn"))
    {
        return;
    }
 
    if(oSession.ResponseHeaders.Count()>0)
    {
        Console.ForegroundColor = ConsoleColor.White;
        for (int i = 0; i < oSession.ResponseHeaders.Count(); i++)
        {
            var s=String.Format("{0,-20}{1}", oSession.ResponseHeaders[i].Name, oSession.ResponseHeaders[i].Value);
            FiddlerApplication.Log.LogString($" {s}");
        }
    }
    if (oSession.ResponseBody != null)
    {
        Console.ForegroundColor = ConsoleColor.White;
        var s = oSession.GetResponseBodyAsString();
        FiddlerApplication.Log.LogString($" {s}");
    }
}

運(yùn)行Fiddler

void FiddlerStart()
{ 
    FiddlerApplication.Log.LogString($"啟動(dòng)程序...");
    //安裝證書
    InstallCertificate();
    //攔截http請求信息事件
    AttachListening();
    //啟動(dòng)Fiddler
    StartupFiddler();
    Console.WriteLine("按任意鍵結(jié)束本地代理監(jiān)聽..." + Environment.NewLine);
    Console.Read();
    //卸載證書
    UninstallCertificate();
    //關(guān)閉Fiddler
    UninstallFiddler();
}

以上代碼展示了從創(chuàng)建證書乾蓬,啟動(dòng)fiddler,監(jiān)聽請求與響應(yīng)惠啄,關(guān)閉fiddler的全過程,不明白還可以查閱FiddlerCore官方文檔

TitaniumProxy

簡介

TitaniumProxy 是一個(gè)跨平臺(tái)任内、輕量級撵渡、低內(nèi)存、高性能的HTTP(S)代理服務(wù)器死嗦,開發(fā)語言為C#,常用于抓包趋距、模擬低帶寬、修改請求等場景越走。

功能特性

  1. 支持HTTP(S)與HTTP 1.1的大部分功能
  2. 支持redirect/block/update 請求
  3. 支持更新Response
  4. 支持HTTP承載的WebSocket
  5. Support mutual SSL authentication
  6. 完全異步的代理
  7. 支持代理授權(quán)與自動(dòng)代理檢測
  8. Kerberos/NTLM authentication over HTTP protocols for windows domain

實(shí)現(xiàn)步驟

以下是使用Titanium.Web.Proxy實(shí)現(xiàn)HTTP代理服務(wù)器的基本步驟:

  1. 安裝Titanium.Web.Proxy庫棚品;
  2. 創(chuàng)建代理服務(wù)器,并設(shè)置基本配置廊敌;
  3. 響應(yīng)事件處理铜跑,可以根據(jù)需要進(jìn)行自定義;
  4. 添加終結(jié)點(diǎn)骡澈;
  5. 啟動(dòng)代理服務(wù)器锅纺,并設(shè)置為系統(tǒng)代理。
    如果你在使用Titanium.Web.Proxy過程中遇到問題肋殴,可以參考相關(guān)文檔或社區(qū)帖子囤锉,也可以嘗試搜索其他解決方案。

創(chuàng)建代理

using System.Net;
using Titanium.Web.Proxy;
using Titanium.Web.Proxy.EventArguments;
using Titanium.Web.Proxy.Http;
using Titanium.Web.Proxy.Models;

var proxyServer = new ProxyServer();

創(chuàng)建證書

// 此代理使用的本地信任根證書 
//proxyServer.CertificateManager.TrustRootCertificate = true;
//proxyServer.CertificateManager.TrustRootCertificate(true);
//使用BouncyCastle庫來生成證書
proxyServer.CertificateManager.CertificateEngine = Titanium.Web.Proxy.Network.CertificateEngine.DefaultWindows; 
proxyServer.CertificateManager.EnsureRootCertificate();
//在Mono之下护锤,只有BouncyCastle將得到支持
//proxyServer.CertificateManager.CertificateEngine = Network.CertificateEngine.BouncyCastle;
proxyServer.CertificateManager.SaveFakeCertificates = true;
proxyServer.CertificateManager.RootCertificate = proxyServer.CertificateManager.LoadRootCertificate();
if (proxyServer.CertificateManager.RootCertificate == null)
{
    Console.WriteLine("正在進(jìn)行證書安裝官地,需要安裝證書才可進(jìn)行https解密,若有提示請確定");
    proxyServer.CertificateManager.CreateRootCertificate();
}

添加端點(diǎn)

顯式端點(diǎn)

var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true)
{
    // 在所有https請求上使用自頒發(fā)的通用證書
    // 通過不為每個(gè)啟用https的域創(chuàng)建證書來優(yōu)化性能
    // 當(dāng)代理客戶端不需要證書信任時(shí)非常有用
   //GenericCertificate = new X509Certificate2(Path.Combine(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "genericcert.pfx"), "password")
};

// 顯式端點(diǎn)是客戶端知道代理存在的地方,因此烙懦,客戶端以代理友好的方式發(fā)送請求
proxyServer.AddEndPoint(explicitEndPoint);

透明端點(diǎn)

透明endpoint 對于反向代理很有用(客戶端不知道代理的存在); 透明endpoint 通常需要一個(gè)網(wǎng)絡(luò)路由器端口來轉(zhuǎn)發(fā)HTTP(S)包或DNS發(fā)送數(shù)據(jù)到此endpoint

var transparentEndPoint = new TransparentProxyEndPoint(IPAddress.Any, 8001, true)
{
    // 客戶端禁用SNI時(shí)要使用的通用證書主機(jī)名
    GenericCertificateName = "google.com"
};
proxyServer.AddEndPoint(transparentEndPoint);

處理事件

添加事件

proxyServer.ServerCertificateValidationCallback += ProxyServer_ServerCertificateValidationCallback; 
proxyServer.BeforeRequest += ProxyServer_BeforeRequest;
proxyServer.BeforeResponse += ProxyServer_BeforeResponse;
explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += ExplicitEndPoint_BeforeTunnelConnectResponse;

proxyServer.AddEndPoint(explicitEndPoint);

處理事件

async Task<bool> OnBeforeTunnelConnect(string hostname)
{
    if (hostname.Contains("rscode.cn"))
    {
        //排除rscode.cn被解密驱入,而是通過安全的TCP隧道中繼
        return await Task.FromResult(true);
    }
    else
    {
        return await Task.FromResult(false);
    }
}
async Task OnBeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
    await Task.Run(() =>
    {
        string hostname = e.HttpClient.Request.RequestUri.Host;
        if (hostname.Contains("rscode.cn"))
        {
            // 排除您不想代理的Https地址
            // 對于使用證書固定的客戶端很有用
            // 例如本例 dropbox.com
            e.DecryptSsl = false;
        }
    });
}
async Task OnRequest(object sender, SessionEventArgs e)
{
    Console.WriteLine(e.HttpClient.Request.Url);
    // read request headers
    var requestHeaders = e.HttpClient.Request.Headers;
    var method = e.HttpClient.Request.Method.ToUpper();
    if ((method == "POST" || method == "PUT" || method == "PATCH"))
    {
        // Get/Set request body bytes
        byte[] bodyBytes = await e.GetRequestBody();
        e.SetRequestBody(bodyBytes);
        // Get/Set request body as string
        string bodyString = await e.GetRequestBodyAsString();
        e.SetRequestBodyString(bodyString);
        // store request 
        // 這樣你就能從響應(yīng)處理器中找到它
        e.UserData = e.HttpClient.Request;
    }
    // 取消帶有自定義HTML內(nèi)容的請求
    // Filter URL
    if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("rscode.cn"))
    {
        e.Ok("<!DOCTYPE html>" +
            "<html><body><h1>" +
            "Website Blocked" +
            "</h1>" +
            "<p>Blocked by titanium web proxy.</p>" +
            "</body>" +
            "</html>");
    }
    // Redirect example
    if (e.HttpClient.Request.RequestUri.AbsoluteUri.Contains("wikipedia.org"))
    {
        e.Redirect("https://www.paypal.com");
    }
}
// Modify response
public async Task OnResponse(object sender, SessionEventArgs e)
{
    // read response headers
    var responseHeaders = e.HttpClient.Response.Headers;
    //if (!e.ProxySession.Request.Host.Equals("medeczane.sgk.gov.tr")) return;
    if (e.HttpClient.Request.Method == "GET" || e.HttpClient.Request.Method == "POST")
    {
        if (e.HttpClient.Response.StatusCode == 200)
        {
            if (e.HttpClient.Response.ContentType != null && e.HttpClient.Response.ContentType.Trim().ToLower().Contains("text/html"))
            {
                byte[] bodyBytes = await e.GetResponseBody();
                e.SetResponseBody(bodyBytes);
                string body = await e.GetResponseBodyAsString();
                e.SetResponseBodyString(body);
            }
        }
    }
    if (e.UserData != null)
    {
        // 從存儲(chǔ)在RequestHandler中的UserData屬性的訪問請求
        var request = (Request)e.UserData;
    }
}
// 允許重寫默認(rèn)的證書驗(yàn)證邏輯
public Task OnCertificateValidation(object sender, CertificateValidationEventArgs e)
{
    // 根據(jù)證書錯(cuò)誤,設(shè)置IsValid為真/假
    if (e.SslPolicyErrors == System.Net.Security.SslPolicyErrors.None)
        e.IsValid = true;
    return Task.CompletedTask;
}
// 允許在相互身份驗(yàn)證期間重寫默認(rèn)客戶端證書選擇邏輯
public Task OnCertificateSelection(object sender, CertificateSelectionEventArgs e)
{
    // set e.clientCertificate to override
    return Task.CompletedTask;
}    

websocket處理

var explicitEndPoint = new ExplicitProxyEndPoint(IPAddress.Any, 8000, true);
//收到CONNECT請求時(shí)觸發(fā)
explicitEndPoint.BeforeTunnelConnectRequest += ExplicitEndPoint_BeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse += ExplicitEndPoint_BeforeTunnelConnectResponse;
private async Task ExplicitEndPoint_BeforeTunnelConnectRequest(object sender, TunnelConnectSessionEventArgs e)
{
    string hostname = e.HttpClient.Request.RequestUri.Host;
    if (!barrageWsHostNames.Contains(hostname))
    {
        e.DecryptSsl = false;
    }
}
private Task ExplicitEndPoint_BeforeTunnelConnectResponse(object sender, TunnelConnectSessionEventArgs e)
{
    string hostname = e.HttpClient.Request.RequestUri.Host;
    if (!barrageWsHostNames.Contains(hostname))
    {
        e.DecryptSsl = false;
    }
    Console.WriteLine($"ExplicitEndPoint_BeforeTunnelConnectResponse url={hostname}");
    if (e.UserData != null)
    {

    }
    return Task.CompletedTask;
}

private async void WebSocket_DataReceived(object sender, DataEventArgs e)
{
    var args = (SessionEventArgs)sender;

    string hostname = args.HttpClient.Request.RequestUri.Host;
    var processid = args.HttpClient.ProcessId.Value;
    var frames = args.WebSocketDecoderReceive.Decode(e.Buffer, e.Offset, e.Count).ToList();

    foreach (var frame in frames)
    {
        base.SendWebSocketData(new WsMessageEventArgs()
        {
            ProcessID = processid,
            HostName = hostname,
            Payload = frame.Data.ToArray(),
            ProcessName = base.GetProcessName(processid)
        });
    }
}

設(shè)為系統(tǒng)代理

//proxyServer.UpStreamHttpProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
//proxyServer.UpStreamHttpsProxy = new ExternalProxy() { HostName = "localhost", Port = 8888 };
foreach (var endPoint in proxyServer.ProxyEndPoints)
Console.WriteLine("Listening on '{0}' endpoint at Ip {1} and port: {2} ",
    endPoint.GetType().Name, endPoint.IpAddress, endPoint.Port);
// 只有顯式代理可以設(shè)置為系統(tǒng)代理!
proxyServer.SetAsSystemHttpProxy(explicitEndPoint);
proxyServer.SetAsSystemHttpsProxy(explicitEndPoint);

打開代理

Console.WriteLine("打開代理");
proxyServer.AddEndPoint(explicitEndPoint);
proxyServer.Start();
proxyServer.SetAsSystemHttpProxy(explicitEndPoint);

關(guān)閉代理

Console.WriteLine("關(guān)閉代理");
proxyServer.ServerCertificateValidationCallback -= ProxyServer_ServerCertificateValidationCallback; 
proxyServer.BeforeRequest -= ProxyServer_BeforeRequest;
proxyServer.BeforeResponse -= ProxyServer_BeforeResponse;
explicitEndPoint.BeforeTunnelConnectRequest -= ExplicitEndPoint_BeforeTunnelConnectRequest;
explicitEndPoint.BeforeTunnelConnectResponse -= ExplicitEndPoint_BeforeTunnelConnectResponse;

proxyServer.Stop();
proxyServer.Dispose();

總結(jié)

TitaniumProxy 和 FiddlerCore 是兩個(gè)不同的 HTTP(S) 代理服務(wù)器,它們有以下一些區(qū)別:

  1. 設(shè)計(jì)和架構(gòu):TitaniumProxy 是一個(gè)重新實(shí)現(xiàn)的 FiddlerCore亏较,具有更合理的框架設(shè)計(jì)和易于擴(kuò)展的特點(diǎn)莺褒。FiddlerCore 可能在某些方面存在設(shè)計(jì)上的不足,如 API 命名不規(guī)范雪情、屬性/字段混用等遵岩。
  2. 性能和資源使用:TitaniumProxy 被宣傳為具有低內(nèi)存和高性能的特點(diǎn)。具體的性能差異可能因?qū)嶋H使用情況而異巡通,但在一些情況下尘执,TitaniumProxy 可能更適合對性能要求較高的場景。
  3. 功能和特性:兩者的功能可能會(huì)有所不同扁达。具體取決于它們的版本和配置正卧。一些可能的差異包括對協(xié)議的支持、代理規(guī)則的靈活性跪解、數(shù)據(jù)過濾和修改的能力等炉旷。
  4. 社區(qū)和支持:FiddlerCore 是由 Telerik 開發(fā)的,可能有更廣泛的社區(qū)和文檔支持叉讥。TitaniumProxy 可能是一個(gè)相對較新的項(xiàng)目窘行,社區(qū)和支持可能相對較小。

在選擇使用哪個(gè)代理服務(wù)器時(shí)图仓,你可以考慮以下因素:

  1. 具體需求:根據(jù)你的具體需求確定所需的功能和特性罐盔。
  2. 性能要求:如果對性能有較高要求,可以評估兩者在實(shí)際使用中的性能表現(xiàn)救崔。
  3. 開發(fā)和集成:考慮與你的開發(fā)環(huán)境和項(xiàng)目的集成難易程度惶看。
  4. 社區(qū)和支持:一個(gè)活躍的社區(qū)和良好的文檔支持可以幫助你解決問題和獲取更多資源。

記得無論用哪種方式創(chuàng)建代理六孵,程序結(jié)束時(shí)都要關(guān)閉代理纬黎,否則電腦為斷網(wǎng);解決斷網(wǎng)的方法就是重新開應(yīng)用,再正常關(guān)閉應(yīng)用即可劫窒。

下一篇將用兩個(gè)實(shí)際案例:美元匯率監(jiān)控和直播間彈幕抓取項(xiàng)目本今,結(jié)合FiddlerCore和TitaniumProxy寫代碼。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末主巍,一起剝皮案震驚了整個(gè)濱河市冠息,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌孕索,老刑警劉巖逛艰,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異搞旭,居然都是意外死亡散怖,警方通過查閱死者的電腦和手機(jī)唐断,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來杭抠,“玉大人,你說我怎么就攤上這事恳啥∑樱” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵钝的,是天一觀的道長翁垂。 經(jīng)常有香客問我,道長硝桩,這世上最難降的妖魔是什么沿猜? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮碗脊,結(jié)果婚禮上啼肩,老公的妹妹穿的比我還像新娘。我一直安慰自己衙伶,他們只是感情好祈坠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著矢劲,像睡著了一般赦拘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上芬沉,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天躺同,我揣著相機(jī)與錄音,去河邊找鬼丸逸。 笑死蹋艺,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的椭员。 我是一名探鬼主播车海,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼隘击!你這毒婦竟也來了侍芝?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤埋同,失蹤者是張志新(化名)和其女友劉穎州叠,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體凶赁,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡咧栗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年逆甜,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片致板。...
    茶點(diǎn)故事閱讀 40,133評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡交煞,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出斟或,到底是詐尸還是另有隱情素征,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布萝挤,位于F島的核電站御毅,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏怜珍。R本人自食惡果不足惜端蛆,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望酥泛。 院中可真熱鬧今豆,春花似錦、人聲如沸柔袁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瘦馍。三九已至歼秽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間情组,已是汗流浹背燥筷。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留院崇,地道東北人肆氓。 一個(gè)月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像底瓣,于是被迫代替她去往敵國和親谢揪。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容