ウェブスクレイピングという言葉がありますが、これはウェブ(特定のHP上)から必要な情報を取り出すものです。
www.fascinatedwithtofu.com
仕事(電子機器開発)上で機械の動作ログがテキストで出てくるのですが、これを解析するのに通常はExcelのマクロで行っています。
機能としては十分なことが可能なのですが、実行速度が遅い。
ここで、これをC#で作ってみようと思いました。
StreamReaderをつかえばできそうなことは容易に想像がつきます。
結果的にはExcel VBAより高速に抽出が完了します。
また、VBAの場合はファイルの読み込み中に他のExcelでの作業ができませんが(できなくもないけど)C#で作れば、Excelのプロセスが使われるわけではないのでExcelの作業を止めることもありません。
UIとしては↓のようなものを作成し、「Target / URL」ボックスは今後作るウェブスクレイピング向け。
Kyewordに目的のIndexを入れて「File」クリックで実行します。
<命名ルール>
デザイナーは敢えて公開しませんが、
ボタンクリックイベントは
「ボタン名_Click」 →ex) private void FileOpen_Click …
チェックボックスの状態はチェックボックスのDefaolt名がcheckBox(Number)だと思うので、checkBoxという名前を残して、
「checkBox名称」 → ex) checkBoxPreview
コンボボックスなら「comboBox名称」→ ex) comboBoxKeyword
というようにつけていくと後々わかりやすいのではないかと思います。
もっといい方法(きちんとした命名ルール)があるかもしれなくて、自作の方法ですが。
<機能>
・テキストまたはそれに準ずるファイルを読み込むことができる。
・Keywordが含まれている「行」を抽出しTextファイルに出力する。
・Previewボックスに出すこともできる。
・上記2つの出力先はチェックボックスで切り替え可能。
・上記チェックボックスがいずれもチェックされていないときはErrorをだす。
・読み込み中は読み込みが実行中であることを示す。(今回はPreviewボックスのグレーアウトと、ボタンの無効化)
・Previewボックスには読み込みが続けて行われても、区別できるようにする(今回は読み込み開始時刻をいれる)
・使用許諾に了承しない人には使わせない
<ロジック設計>
プログラムを実行するにはそのプログラムが正しく動作する条件が必要です。
まず捜索するKeywordが必要です。これがないときは基本的にはErrorです。
しかし、「Blank」というのもありといえばあり。
出力条件はそのプログラムの実行結果の出力なので、これがないとなにも意味を成しません。
この条件判断はなくてもErrorが出るわけではありませんが、その他のErrorがあるのか、本当に動作した結果何も出力がないのか、の判断がつかないのは困るので入れておくほうがいいと考えられます。
<実行結果>
テスト用の題材としてはWikipediaのあるページのHTMLソースをテキストに保存したものを使いました。
例えば、"<h" をKeywordにすると、<h1、<h2、<h3…などの含まれた行だけを取り出すことができます。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Collections; namespace mojiretsu { public partial class Form1 : System.Windows.Forms.Form { private void Form1_Load(object sender, EventArgs e) { Boolean UserSet = false; var listKeyword = ""; try { StreamReader srKeyword = new StreamReader("ListKeyword.txt"); while ((listKeyword = srKeyword.ReadLine()) != null) // ストリームの末尾まで繰り返す { if (listKeyword != "123456789012") { comboBoxKeyword.Items.Add(listKeyword); } else { UserSet = true; } } } catch { MessageBox.Show("Keyword List is not found, and make it."); using (System.IO.FileStream hStream = System.IO.File.Create("ListKeyword.txt")) { // 作成時に返される FileStream を利用して閉じる if (hStream != null) { hStream.Close(); } } } if (UserSet == false) { if (MessageBox.Show("The producer does not compensate for any damage using this software.", "License confirmation", MessageBoxButtons.OKCancel) != DialogResult.OK) { MessageBox.Show("Not agree and can not use this."); Close(); } } } String Keyword; public Form1() { InitializeComponent(); } private void FileOpen_Click(object sender, EventArgs e) { if (textBoxURL.Text == "") { if (keywordCheck() == true) { if (writeOutCheck() == true) { FileOpen(); } } } else //URLがあったら { } } private void buttonGethtml_Click(object sender, EventArgs e) { //作成中 } public Boolean keywordCheck() { Keyword = comboBoxKeyword.Text; if (Keyword == "") { if (MessageBox.Show("Kyeword is Blank is OK ?", "Notice", MessageBoxButtons.OKCancel) == DialogResult.OK) { return true; } return false; } else { return true; } } public bool writeOutCheck() { if (checkBoxWriteOut.Checked == false && checkBoxPreview.Checked == false) { MessageBox.Show("Select output"); return false; } else { return true; } } public void FileOpen() { DateTime dt = DateTime.Now; string date = dt.ToString("yyyy_MM_dd_HH_mm_ss"); OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { ViewBoxBackColorSet(); textBoxPreview.AppendText(dt.ToString("HH:mm:ss" + Environment.NewLine)); // string[] StrArryData = new string[3]; // 1行分のデータを格納する作業オブジェクト using (var sr = new StreamReader(ofd.FileName)) //型はVariant { int lineCount = 0; if (checkBoxWriteOut.Checked == true) { using (StreamWriter writer = new StreamWriter(date + ".txt", true)) { //インデックス writer.Write("Souce File Name = " + ofd.FileName + Environment.NewLine); writer.Write("Keyword = " + Keyword + Environment.NewLine + "" + Environment.NewLine); writer.Write("======================= " + Environment.NewLine + Environment.NewLine + Environment.NewLine); } } var line = ""; while ((line = sr.ReadLine()) != null) // ストリームの末尾まで繰り返す { int index_check = line.IndexOf(Keyword); //含まれてないときは"-1" if (index_check > -1) { lineCount++; if (checkBoxPreview.Checked == true) { textBoxPreview.AppendText(line + Environment.NewLine); //追記モード } if (checkBoxWriteOut.Checked == true) { using (StreamWriter writer = new StreamWriter(date + ".txt", true)) { writer.Write(line); writer.Write(Environment.NewLine); } } } } labelLineCount.Text = lineCount.ToString(); ViewBoxBackColorReset(); } } } private void buttonClear_Click(object sender, EventArgs e) { textBoxPreview.ResetText(); comboBoxKeyword.ResetText(); textBoxPreview.ResetText(); labelLineCount.Text = "0"; textBoxURL.ResetText(); } private void buttonKeywordOpen_Click(object sender, EventArgs e) { System.Diagnostics.Process.Start("notepad.exe", @"""ListKeyword.txt"""); } public void ViewBoxBackColorSet() { textBoxPreview.BackColor = Color.FromArgb(0xdd, 0xdd, 0xdd); buttonGethtml.Enabled = false; buttonFileOpen.Enabled = false; buttonClear.Enabled = false; buttonKeywordOpen.Enabled = false; } public void ViewBoxBackColorReset() { textBoxPreview.BackColor = Color.White; buttonGethtml.Enabled = true; buttonFileOpen.Enabled = true; buttonClear.Enabled = true; buttonKeywordOpen.Enabled = true; } } } }