プログラム中から、Webサイト検索を行い、その結果得られたテキストから必要な部分を正規表現で抽出し、必要なデータを集める作業を行いたいときがあります。
そのプログラムを構成する部分の1つ、クエリ文字を添付しWebサイト検索を行い、検索結果として表示されるWebサイトをテキストとして取得する方法について考えます。
HttpClientクラスを使って、Bing検索を行う
アプリケーションからHTTPのリクエストする方法が紹介されているWebサイトの記事は、多くありますが、理解するためには、何か前提知識が必要なのか、よくわからないことが多いです。
わかりそうな、Webサイトの記事を手がかりに、思考錯誤で動作を検証します。
Web検索の挙動
google検索で、以下の3つのキーワードで検索を行いたい場合、
- httpclient
- c#
- post
ブラウザのアドレスバーに入力する必要のあるのは、以下の文字列です。
https://www.bing.com/search?q=HttpClient+C%23+post
プロジェクトの作成
新しいプロジェクトを作成します。
WPFアプリを選択し、次へをクリックします。
それぞれのファイルに、以下のコードを入力します。※MainWindow.xamlコードの最初の行は、自動生成されたコードを、そして、MainWindow.xaml.csコードのnamespaceも自動生成されたものを使用してください。
<Window x:Class="PostRequest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="GetHtmlDocument" Height="250" Width="350">
<DockPanel>
<DockPanel DockPanel.Dock="Top">
<Button DockPanel.Dock="Right" Click="Button_Click">Browse</Button>
<TextBox Name="queryBox">httpclient c# post</TextBox>
</DockPanel>
<TextBox Name="sendUrl" DockPanel.Dock="Top">sendUrl</TextBox>
<TextBox Name="htmlDocument">TextBox</TextBox>
</DockPanel>
</Window>
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Windows;
namespace PostRequest
{
/// <summary>
/// MainWindow.xaml の相互作用ロジック
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private static HttpClient client = new HttpClient();
private async void Button_Click(object sender, RoutedEventArgs e)
{
// クッキーを有効にする
var handler = new HttpClientHandler()
{
UseCookies = true,
};
// 送信するクエリを作成する
var parameters = new Dictionary<string, string>()
{
{ "p", queryBox.Text },
};
// ユーザーエージェントを設定する
client.DefaultRequestHeaders.Add("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) like Gecko");
// ロケールを設定する
client.DefaultRequestHeaders.Add("Accept-Language", "ja-JP");
// タイムアウトを設定する
client.Timeout = TimeSpan.FromSeconds(10.0);
// リクエスト文字列を確認する
sendUrl.Text = $"https://www.bing.com/search?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}";
// クエリをpostして、結果をテキストボックスに格納する
var response = await client.GetAsync($"https://www.bing.com/search?{await new FormUrlEncodedContent(parameters).ReadAsStringAsync()}");
htmlDocument.Text = response.ToString();
}
}
}
$”{}”は、C#6.0から、登場した文字列補間構文です。
実行結果
ブラウザに、「https://www.bing.com/search?q=HttpClient+C%23+post」を入力したときのソースと異なります。しかし、「https://www.bing.com/search?p=httpclient+c%23+post」が、送信されており、ステータスコードが、200なので、リクエストは、成功しています。
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
{
Transfer-Encoding: chunked
Cache-Control: private
P3P: CP="NON UNI COM NAV STA LOC CURa DEVa PSAa PSDa OUR IND"
Set-Cookie: _EDGE_S=F=1&SID=2B4073E6BCD16EDB270563C1BD8C6F5A&mkt=ja-jp; domain=.bing.com; path=/; HttpOnly
Set-Cookie: ULC=; domain=.bing.com; expires=Tue, 27-Apr-2021 12:53:36 GMT; path=/
Set-Cookie: _HPVN=CS=eyJQbiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiUCJ9LCJTYyI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiSCJ9LCJReiI6eyJDbiI6MSwiU3QiOjAsIlFzIjowLCJQcm9kIjoiVCJ9LCJBcCI6dHJ1ZSwiTXV0ZSI6dHJ1ZSwiTGFkIjoiMjAyMS0wNC0yOFQwMDowMDowMFoiLCJJb3RkIjowLCJEZnQiOm51bGwsIk12cyI6MCwiRmx0IjowLCJJbXAiOjF9; domain=.bing.com; expires=Fri, 28-Apr-2023 12:53:36 GMT; path=/
X-SNR-Routing: 1
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
X-MSEdge-Ref: Ref A: 32F7CD12565A430483846F7BE77A4F29 Ref B: TYBEDGE0914 Ref C: 2021-04-28T12:53:36Z
Date: Wed, 28 Apr 2021 12:53:35 GMT
Content-Type: text/html; charset=utf-8
}
クッキーを有効、ユーザーエージェントを設定、ロケールを設定、タイムアウトの設定の有無では、得られた結果には差はありませんでした。
teratailで質問した
teratailで質問したところ、SurferOnWww さんから、「https://www.bing.com」は、アプリケーションの動作確認に適切ではなく、自作などを用意して動作が明確な「Web API アプリ」や他の Web API サイトで動作確認をしたほうが良いとアドバイスを頂きました。しかし、私は、現在、ASP.NETやPHPなどのサーバー・アプリケーションを作成できる知識を持っていません。
radian さんからは、Fiddler で確認できるという情報をいただきました。