馬情報のHTMLデータ
HTML文章中のレース情報の下の方にある horseList に馬情報が埋め込まれています。その horseList は頭数分あります
馬情報は、下記下線中の要素 Waku(枠番)、Umaban(馬番)、HorseName(馬名)、Barei(馬齢)、Txt_C(斤量)、Jockey(騎手)、Trainer(厩舎)、Weight(馬体重) に埋め込まれています
馬情報の取得
プログラム的には、Waku、Umaban、HorseName、Barei、Txt_C、Jockey、Trainer、WeightをキーワードにしてHTMLから抽出すればデータ取得できることになります。ここでは下記クラスにデータを格納しています
/*************************/
/* 馬情報クラス */
/*************************/
// オッズと人気はうまく取れないので削除。多分随時変更して表示するので、最初の取得ドキュメントに表示データが入ってこない為と思われる
public class HorseInfo
{
public InfoData<int> WakuNum = new InfoData<int>( -1 ); // 枠番
public InfoData<int> HorseNum = new InfoData<int>( -1 ); // 馬番
public InfoData<string> Horse = new InfoData<string>( "" ); // 馬名
public InfoData<string> HorseLink = new InfoData<string>( "" ); // 馬名リンク
public InfoData<string> Gender = new InfoData<string>( "" ); // 性別
public InfoData<int> Age = new InfoData<int>( -1 ); // 年齢
public InfoData<double> Weight = new InfoData<double>(); // 斤量
public InfoData<string> Jockey = new InfoData<string>( "" ); // 騎手
public InfoData<string> JockeyLink = new InfoData<string>( "" ); // 騎手リンク
public InfoData<string> Barn = new InfoData<string>( "" ); // 厩舎
public InfoData<double> HorseWeight = new InfoData<double>(); // 馬体重
public InfoData<double> HorseWeightDiff = new InfoData<double>(); // 馬体重差
public List<HistoryInfo> History = new List<HistoryInfo>(); // 履歴情報
}
まず、Htmlの文字列取得を GetHtmlText() で取得し、HorseList を頭数分取得し nodes 配列に格納して、各馬毎の馬情報取得を GetHorseInfo() で行う。以下の Info 変数は HorseInfo クラスです
string htmlText = GetHtmlText( Url );
if( htmlText == "" )
{
return false;
}
var htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml( htmlText );
var nodes = htmlDoc.DocumentNode.SelectNodes( "//tr[@class=\"HorseList\"]" );
if( nodes == null )
{
return false;
}
// 馬情報クリア
Info.Clear();
for( int index = 0; index < nodes.Count; index++ )
{
// 各馬毎の馬情報取得
GetHorseInfo( nodes[ index ], out HorseInfo info );
// 各馬毎の馬情報セット
Info.Add( info );
}
return true;
}
GetHorseInfo() 関数は、ノード nodes[ index ] を引数としてコールされます。このノード内から Waku、Umaban、HorseName、Barei、Txt_C、Jockey、Trainer、Weight をキーワードにしてHTMLからデータを抽出します
馬齢性別の Barei については、地方競データの名称が Age なので両方に対応させてます
斤量についてはTxt_C で取得しています。馬齢性別でも Txt_C がセットされているので2つ取得されるかとも思ったのですが、理由は不明ですが1つで取得できています(とりあえず様子見)
騎手については、地方競馬では span、中央競馬では td で定義されているので両方に対応させてます
・馬名には、レース履歴情報がリンクしているので child.GetAttributeValue( “href”, null ) でリンク先を取得します
・馬齢性別からは、性別と年齢を取得します
・馬体重からは、馬体重と体重変化を取得します
// Node:馬情報が入ったURL内ノード
// Info:取得した馬情報
private static void GetHorseInfo( HtmlNode Node, out HorseInfo Info )
{
Info = new HorseInfo();
var htmlDoc = new HtmlAgilityPack.HtmlDocument();
htmlDoc.LoadHtml( Node.InnerHtml );
string strData;
// 枠番取得
var nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Waku\")]" );
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
if( Int32.TryParse( strData, out int result ))
{
Info.WakuNum.Data = result;
}
}
// 馬番取得
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Umaban\")]" );
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
if( Int32.TryParse( strData, out int result ))
{
Info.HorseNum.Data = result;
}
}
// 馬名取得
nodes = htmlDoc.DocumentNode.SelectNodes( "//span[starts-with(@class, \"HorseName\")]" );
if( nodes != null )
{
strData = nodes[ 0 ].InnerText.ToString().Replace("\n","");// ノード内の文字列取得(改行無視)
Info.Horse.Data = strData;
foreach( HtmlNode child in nodes[ 0 ].ChildNodes )
{
strData = child.GetAttributeValue( "href", null );
if(( strData != null ) && ( strData != "" ))
{
Info.HorseLink.Data = strData;
break;
}
}
}
// 馬齢性別取得
// 地方競馬の場合
nodes = htmlDoc.DocumentNode.SelectNodes( "//span[starts-with(@class, \"Age\")]" );
if( nodes == null )
{
// 中央競馬の場合
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Barei\")]" );
}
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
if( strData.Contains( "牡" ))
{
Info.Gender.Data = "牡";
}
if( strData.Contains( "牝" ))
{
Info.Gender.Data = "牝";
}
if( strData.Contains( "セ" ))
{
Info.Gender.Data = "セ";
}
if( Info.Gender.Data != "" )
{
if( Int32.TryParse( strData.Replace( Info.Gender.Data, "" ), out int result ))
{
Info.Age.Data = result;
}
}
}
// 斤量取得
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Txt_C\")]" );
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
if( Double.TryParse( strData, out double result ))
{
Info.Weight.Data = result;
}
}
// 騎手取得
// 地方競馬の場合
nodes = htmlDoc.DocumentNode.SelectNodes( "//span[starts-with(@class, \"Jockey\")]" );
if( nodes == null )
{
// 中央競馬の場合
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Jockey\")]" );
}
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
Info.Jockey.Data = strData;
foreach( HtmlNode child in nodes[ 0 ].ChildNodes )
{
strData = child.GetAttributeValue( "href", null );
if(( strData != null ) && ( strData != "" ))
{
Info.JockeyLink.Data = strData;
break;
}
}
}
// 厩舎取得
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Trainer\")]" );
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
Info.Barn.Data = strData;
}
// 馬体重取得
nodes = htmlDoc.DocumentNode.SelectNodes( "//td[starts-with(@class, \"Weight\")]" );
if( nodes != null )
{
strData = GetInnerStr( nodes[ 0 ] ); // ノード内の文字列取得
GetUmaWeight( strData, out double weight, out double weightDiff );
Info.HorseWeight.Data = weight;
Info.HorseWeightDiff.Data = weightDiff;
}
}