目次
概要
指定したURL(Webページ)にアクセスし、レスポンスボディ(HTMLやテキスト)を文字列として取得する最も基本的な実装です。 System.Net.Http.HttpClient の GetStringAsync メソッドを使用することで、HTTP GETリクエストの発行から文字列への変換までを1行で完結させます。
仕様(入出力)
- 入力: 取得対象のURL(例: ニュースサイトのトップページ)。
- 出力: 取得したHTMLソースコードの文字数と、先頭部分の抜粋。
- 前提: .NET標準ライブラリ(
System.Net.Http)を使用。インターネット接続が必要。
基本の使い方
HttpClient インスタンス(シングルトン推奨)の GetStringAsync にURLを渡します。
// 静的フィールドでインスタンスを共有
private static readonly HttpClient sharedClient = new HttpClient();
public async Task PrintHtmlAsync()
{
// 非同期でテキストを取得
string html = await sharedClient.GetStringAsync("https://www.example.com");
Console.WriteLine(html);
}
コード全文
ここでは「自社サイトの利用規約ページを取得して内容を確認する」というシナリオで実装します。 例外処理を含め、実務で使える形にしています。
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
// 【重要】HttpClientは都度newせず、アプリケーション全体で共有する
// これによりソケット枯渇問題(Socket Exhaustion)を防ぎます
private static readonly HttpClient _httpClient = new HttpClient();
static async Task Main()
{
// 取得対象のURL(サンプルとしてexample.comを使用)
string targetUrl = "https://www.example.com";
Console.WriteLine($"リクエスト送信中: {targetUrl}");
try
{
// タイムアウトを明示的に設定(デフォルトは100秒)
_httpClient.Timeout = TimeSpan.FromSeconds(10);
// WebサーバーからHTMLを文字列として取得
string content = await _httpClient.GetStringAsync(targetUrl);
Console.WriteLine("--- 取得成功 ---");
Console.WriteLine($"データサイズ: {content.Length} 文字");
Console.WriteLine("--- 先頭 500文字 ---");
// 長すぎる場合は切り詰めて表示
string preview = content.Length > 500
? content.Substring(0, 500) + "..."
: content;
Console.WriteLine(preview);
}
catch (HttpRequestException ex)
{
// 404 Not Found や DNSエラーなど
Console.WriteLine($"[通信エラー] {ex.Message}");
if (ex.StatusCode.HasValue)
{
Console.WriteLine($"HTTPステータス: {ex.StatusCode}");
}
}
catch (TaskCanceledException)
{
// タイムアウト時
Console.WriteLine("[タイムアウト] 応答がありませんでした。");
}
catch (Exception ex)
{
// その他の予期せぬエラー
Console.WriteLine($"[システムエラー] {ex.Message}");
}
}
}
カスタムポイント
- ヘッダーの追加: APIや特定のサイトへアクセスする場合、認証トークンやUser-Agentが必要になることがあります。C#
_httpClient.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0"); _httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer my_token"); - バイト配列での取得: 画像データのダウンロードや、エンコーディング指定が必要な場合(Shift-JISのサイトなど)は、
GetStringAsyncではなくGetByteArrayAsyncを使用し、Encodingクラスで手動変換します。
注意点
- インスタンスのライフサイクル: コード内でも触れましたが、
using (var client = new HttpClient())でリクエストごとに生成・破棄を行うのはアンチパターンです。高負荷時にポートが枯渇します。必ずstaticで共有するか、IHttpClientFactoryを使用してください。 - DNSの更新:
staticで持ち続けるとDNSの変更が反映されない問題がありますが、.NET Core 2.1以降(.NET 5/6/8含む)ではSocketsHttpHandlerが内部で適切にハンドリングするため、基本的にはシングルトンで問題ありません。 - 非同期の徹底:
GetStringAsync(...).Resultのように同期的に待機すると、GUIアプリやASP.NETでデッドロックの原因になります。必ずawaitを使用してください。
応用
ストリームとして処理する(メモリ節約)
巨大なHTMLやテキストを取得する場合、全データを文字列としてメモリに展開する GetStringAsync は非効率です。GetStreamAsync を使い、読み込みながら処理します。
using (var stream = await _httpClient.GetStreamAsync(targetUrl))
using (var reader = new System.IO.StreamReader(stream))
{
// 1行ずつ読み込んで処理(メモリ消費を抑える)
while (!reader.EndOfStream)
{
string? line = await reader.ReadLineAsync();
if (line != null && line.Contains("<title>"))
{
Console.WriteLine($"タイトルタグ発見: {line}");
}
}
}
まとめ
実運用では、ネットワークエラーやタイムアウトを想定した例外処理(try-catch)が必須です。
Web上のテキストデータを取得するには HttpClient.GetStringAsync が最もシンプルです。
HttpClient は「使い捨て」ではなく「使い回す」クラスです。
