プログラミング・動画編集 備忘録

プログラミングや動画編集についての備忘録です

C#で任意のサイトの情報を抜き取る - ウェブスクレイピングはじめの一歩

はじめに

本記事はニコニコ動画の動画説明文をツールから編集するにあたって、まずはウェブサイトから情報を抜き取るための簡単なサンプルを紹介します。
ソースコードは最低限動きを確認するために作ったもので、細かい対処をしていませんのでご注意ください。

なるべくStep by Stepでわかりやすいようにと思ったのですが、とりあえず書き殴りの状態です。
一番知ってほしいのは、ブラウザ上でF12を押下して表示する開発ツールがめちゃくちゃ便利だというです。

背景

今更ながら(2016/12/21から)動画投稿に手を染めました。
SkyrimのMod開発の楽しさを伝えたり、自作Modや自作ツールを紹介するためです。
以下の動画をYouTubeニコニコ動画に投稿してみたのですが、やはりというかニコニコ動画の方が見てもらえます。


この際、YouTubeニコニコ動画で同じタイトル、同じ説明をそれぞれに適用するのが面倒な事や、仕様の違いで実現できないことや、なんとなく使いづらいさを感じたので、管理・編集ツールを作ろうと思った次第です。(SkyrimのMod開発から大分脱線してきました)

対象のサイト内で情報取得したいタグを発見する方法

注意:Google Chromeを使用している場合の説明です。IEでも同様のことが可能です)

まずは、投稿した動画を選ぶために、一覧的なところから情報を取得することにしましたので、ニコニコ動画の動画投稿の画面を表示します。
f:id:rrryutaro:20161222112215p:plain

F12を押下して開発ツールを表示し、要素を選択するツールをクリックします。(ショートカットはCtrl + Shift + C)
f:id:rrryutaro:20161222112414p:plain

すると、画面内にカーソルを合わせると、選択範囲のタグが表示されます。
ここでは、投稿した動画の一覧表示にあたると思われる部分にカーソルを合わせてクリックし確定します。
f:id:rrryutaro:20161222112740p:plain

htmlソースが表示されたウィンドウにて該当のタグが選択されています。
ここの配下に投稿動画の一覧があることになりますので、まずはこのタグを取得するにあたって、参考にするためにXPathを取得します。
f:id:rrryutaro:20161222113416p:plain

次の内容が取得できました。
「//*[@id="video"]/div[5]」
これでidがわかりましたので、GetElementByIdで取得できます。また、対象のタグはGetElementByIdで取得した場合、子要素のIndexが5で取得することになります。

HtmlElement el = webBrowser1.Document.GetElementById("video").Children[5];

後は、そこから投稿動画のタイトルやアドレスを取得します。

同じようにして今度は投稿動画の編集画面を表示し、タイトルと動画説明文の項目を選択して要素を確認します。
f:id:rrryutaro:20161222114103p:plain

タイトルは、"movie_title" というId、動画説明文は、"movie_detail" というIdが定義されていることがわかりましたので、GetElementByIdで取得できます。
後は、これらを取得してフォームに表示するれば、ニコニコ動画での動画一覧や動画タイトル、動画説明文の取得ができるようになります。

フォームのデザイン

次のような感じでデザインします。
f:id:rrryutaro:20161222110312p:plain

コード

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;

namespace RniconicoEditor
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void fileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            webBrowser1.Navigate("http://www.nicovideo.jp/my/video");
        }

        private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
        {
            System.Diagnostics.Debug.Print(e.Url.ToString());

            if (e.Url.Equals("http://www.nicovideo.jp/my/video"))
            {
                HtmlElement el = webBrowser1.Document.GetElementById("video").Children[5];
                for (int i = 1; i < el.Children.Count; i++)
                {
                    HtmlElement elm = el.Children[i].Children[1].Children[0].Children[0];
                    if (elm != null)
                    {
                        string key = elm.GetAttribute("href").Replace("http://www.nicovideo.jp/watch/", "");
                        treeView1.Nodes.Add(key, elm.InnerText).Tag = key.Replace("sm", "");
                    }
                }
            }
            else if (0 <= e.Url.ToString().IndexOf("http://www.upload.nicovideo.jp/edit?f="))
            {
                textBox1.Text = webBrowser1.Document.GetElementById("movie_title").GetAttribute("value");
                textBox2.Text = webBrowser1.Document.GetElementById("movie_detail").OuterText;
            }
        }

        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            webBrowser1.Navigate($"http://www.upload.nicovideo.jp/edit?f={e.Node.Tag}");
        }
    }
}

結果

次のような感じになります。
f:id:rrryutaro:20161222063112p:plain

Qiitaで作り直した記事

qiita.com

以上