前提条件#
- .NET 6.0+
- Firecrawl APIキー — 無料で取得できます
設定#
appsettings.json に API key を追加します:
{ "Firecrawl": { "ApiKey": "fc-YOUR-API-KEY", "BaseUrl": "https://api.firecrawl.dev/v2" }}または、環境変数 / ユーザーシークレットを使用します:
export Firecrawl__ApiKey=fc-YOUR-API-KEYサービスを作成#
Services/FirecrawlService.cs を作成します。
using System.Net.Http.Headers;using System.Text;using System.Text.Json;public class FirecrawlService{ private readonly HttpClient _http; private readonly string _baseUrl; public FirecrawlService(IConfiguration config) { _baseUrl = config["Firecrawl:BaseUrl"] ?? "https://api.firecrawl.dev/v2"; _http = new HttpClient(); _http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", config["Firecrawl:ApiKey"]); } public async Task<JsonDocument> SearchAsync(string query, int limit = 5) { var content = new StringContent( JsonSerializer.Serialize(new { query, limit }), Encoding.UTF8, "application/json"); var response = await _http.PostAsync($"{_baseUrl}/search", content); response.EnsureSuccessStatusCode(); return JsonDocument.Parse(await response.Content.ReadAsStringAsync()); } public async Task<JsonDocument> ScrapeAsync(string url) { var content = new StringContent( JsonSerializer.Serialize(new { url }), Encoding.UTF8, "application/json"); var response = await _http.PostAsync($"{_baseUrl}/scrape", content); response.EnsureSuccessStatusCode(); return JsonDocument.Parse(await response.Content.ReadAsStringAsync()); } public async Task<JsonDocument> InteractAsync(string url, string prompt, string? followUp = null) { // 1. ブラウザセッションを開くためにスクレイピング var scrapeContent = new StringContent( JsonSerializer.Serialize(new { url, formats = new[] { "markdown" } }), Encoding.UTF8, "application/json"); var scrapeRes = await _http.PostAsync($"{_baseUrl}/scrape", scrapeContent); scrapeRes.EnsureSuccessStatusCode(); var scrapeDoc = JsonDocument.Parse(await scrapeRes.Content.ReadAsStringAsync()); var scrapeId = scrapeDoc.RootElement .GetProperty("data").GetProperty("metadata").GetProperty("scrapeId").GetString(); // 2. 最初のプロンプトを送信 var firstPrompt = new StringContent( JsonSerializer.Serialize(new { prompt }), Encoding.UTF8, "application/json"); await _http.PostAsync($"{_baseUrl}/scrape/{scrapeId}/interact", firstPrompt); // 3. フォローアッププロンプトを送信 JsonDocument? result = null; if (followUp != null) { var followUpContent = new StringContent( JsonSerializer.Serialize(new { prompt = followUp }), Encoding.UTF8, "application/json"); var followUpRes = await _http.PostAsync( $"{_baseUrl}/scrape/{scrapeId}/interact", followUpContent); followUpRes.EnsureSuccessStatusCode(); result = JsonDocument.Parse(await followUpRes.Content.ReadAsStringAsync()); } // 4. セッションを閉じる await _http.DeleteAsync($"{_baseUrl}/scrape/{scrapeId}/interact"); return result ?? scrapeDoc; }}登録して使う#
Program.cs で以下を記述します:
var builder = WebApplication.CreateBuilder(args);builder.Services.AddSingleton<FirecrawlService>();var app = builder.Build();app.MapPost("/api/search", async (FirecrawlService firecrawl, SearchRequest req) =>{ var result = await firecrawl.SearchAsync(req.Query, req.Limit); return Results.Ok(result.RootElement);});app.MapPost("/api/scrape", async (FirecrawlService firecrawl, ScrapeRequest req) =>{ var result = await firecrawl.ScrapeAsync(req.Url); return Results.Ok(result.RootElement);});app.MapPost("/api/interact", async (FirecrawlService firecrawl, InteractRequest req) =>{ var result = await firecrawl.InteractAsync(req.Url, req.Prompt, req.FollowUp); return Results.Ok(result.RootElement);});app.Run();record SearchRequest(string Query, int Limit = 5);record ScrapeRequest(string Url);record InteractRequest(string Url, string Prompt, string? FollowUp = null);実行#
dotnet run試してみる#
# ウェブを検索するcurl -X POST http://localhost:5000/api/search \ -H "Content-Type: application/json" \ -d '{"query": "firecrawl web scraping"}'# ページをスクレイピングするcurl -X POST http://localhost:5000/api/scrape \ -H "Content-Type: application/json" \ -d '{"url": "https://example.com"}'# ページをInteractするcurl -X POST http://localhost:5000/api/interact \ -H "Content-Type: application/json" \ -d '{"url": "https://www.amazon.com", "prompt": "Search for iPhone 16 Pro Max", "followUp": "Click on the first result and tell me the price"}'
