2014年5月29日木曜日

C#でWebからデータを取ってくる

C#でwebからデータを取ってくるってことはあまり考えたことがなかったのですが、ちょっとプロ野球の得点分布を知りたいなと思った時に、いちいちデータを手打ちで集めるのも面倒だから自動化出来ないかなぁと考えて色々さがしてみたところ、C#でもhtmlのDOMを自在に操れるHtmlAgilityPackなるものがあるらしいのでちょっとテスト。

使い方としてはまず using System.Net でネットワーク関連のusingをもって来ておいて、HttpWebRequestとHttpWebResponseでデータを読み込みます。この時にもっと単純に取ってくるWebClientというクラスもあるのですが、それよりもrequestとresponseでストリーミングで読み込んだほうがUI(フォーム表示用)スレッドと読み込みスレッドを分離できるので、読み込み時にフォームが固まることを防げるのでよいらしいです。

WebClientよりHttpWebRequestを使った方がいい理由
http://d.hatena.ne.jp/kabakiyo/20120224/1330066622

あとはその読み込んだstringをHtmlAgilityPackにほり込んで、SelectNodesでjQuery的に検索してやれば勝手にほしいとこだけを検索して出してくれるという流れです。とってもシンプルでいいですね。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;

namespace web
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        string baseurl = "http://baseball.yahoo.co.jp/npb/game/";

        private void button1_Click(object sender, EventArgs e)
        {
            DateTime dt_now = DateTime.Now;
            string date = dt_now.ToShortDateString().Replace("/", "");

            // 今日の試合を読み込むためにurlを加工
            string url = baseurl + date + "01" + "/stats";
            //ex).url = http://baseball.yahoo.co.jp/npb/game/2014052801/stats

            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "GET";
            HttpWebResponse res = (HttpWebResponse)req.GetResponse();
            Stream s = res.GetResponseStream();
            StreamReader sr = new StreamReader(s);
            string context = sr.ReadToEnd();
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(context);

            HtmlAgilityPack.HtmlNodeCollection _nodes = doc.DocumentNode.SelectNodes("/html[1]/body[1]/table[1]/tr");
            if (_nodes == null)
                break;
            foreach (var node in _nodes)
            {
                textBox1.Text += node.InnerText + "\r\n";
            }
        }
    }
}

0 件のコメント:

コメントを投稿