DOBON.NET DOBON.NETプログラミング掲示板過去ログ

HTMLの中から日本文字の抽出

環境/言語:[.NET2005 WindowsXP]
分類:[.NET]

Htmlの中に含まれる日本語文字のみを抽出したいのですが
どなたかお分かりになる方よろしくお願いします。
検索でも調べてみたのですが、どうも見当たりません。
日本文字は、2バイトですので2バイトコードのみ抽出すればよいと
思うのですが、適当な関数あれば教えてください。
以前、何かでデータの中から2バイトコード(日本語)を抽出する関数?
があったと思うのですが見当たりません。
> 日本文字は、2バイトですので2バイトコードのみ抽出すればよいと
> 思うのですが、適当な関数あれば教えてください。
その認識がまずいと思います。

.NETでの文字列(String型)は常にUnicodeです。
一般的な漢字と、俗に言う半角英数文字は同じ2バイト(=1個のChar型)で表現されます。
この時点で「2バイトかどうかの判定」は意味を成さないと考えて下さい。

また、対象のHTMLはどのように取り出すつもりですか?
直接ファイルから読み込むのであれば、文字コードがかなりのパターンとなるでしょう。
日本語を扱う文書だけでもUnicode(UTF-8他)、ShiftJIS、EUC-JP、JISはあります。
ShiftJISとUnicode間は標準ライブラリで変換できますが、EUC-JPやJISについては別のライブラリを使うことになりそうです。
(WebBrowserコントロールで読みこんで、部分的に取得するのであれば問題ないかも)

-----

今の方針に対する指摘はこのあたりで止めておき、確認させて下さい。

「なぜ日本(語)文字列だけを抽出したいのですか?」

どのような目的で、どのような文字列を抽出したいのかがもう少し具体的に分かれば、別の手法が提案される可能性があります。
■No22061に返信(Azuleanさんの記事)
>>日本文字は、2バイトですので2バイトコードのみ抽出すればよいと
>>思うのですが、適当な関数あれば教えてください。
> その認識がまずいと思います。
>
> .NETでの文字列(String型)は常にUnicodeです。
> 一般的な漢字と、俗に言う半角英数文字は同じ2バイト(=1個のChar型)で表現されます。
> この時点で「2バイトかどうかの判定」は意味を成さないと考えて下さい。
>
> また、対象のHTMLはどのように取り出すつもりですか?
> 直接ファイルから読み込むのであれば、文字コードがかなりのパターンとなるでしょう。
> 日本語を扱う文書だけでもUnicode(UTF-8他)、ShiftJIS、EUC-JP、JISはあります。
> ShiftJISとUnicode間は標準ライブラリで変換できますが、EUC-JPやJISについては別のライブラリを使うことになりそうです。
> (WebBrowserコントロールで読みこんで、部分的に取得するのであれば問題ないかも)
>
> -----
>
> 今の方針に対する指摘はこのあたりで止めておき、確認させて下さい。
>
> 「なぜ日本(語)文字列だけを抽出したいのですか?」
>
> どのような目的で、どのような文字列を抽出したいのかがもう少し具体的に分かれば、別の手法が提案される可能性があります。


Azulean 様

早速のご指摘ありがとうございます。

一般的な漢字と、俗に言う半角英数文字は同じ2バイト(=1個のChar型)で表現されます。
よく分かりました、やはりやっかいなことになりそうですね

現在のシステムは、WebBrowserコントロールで読みこんでHTMLを解析しタイトルおよび対象記事の範囲を絞り込むところまではできています。

対象範囲 = <DVI 〜〜 </DVI>
この〜〜中に取得したい日本文字があります。
目的は、対象サイトを自動巡回し目的とするカテゴリーのスクラップデータの蓄積です。
HTMLタグだけ削除できればほぼ目的は達しられるのですが
何か手はありますでしょうか?
■No22064に返信(ふろんさんの記事)
> HTMLタグだけ削除できればほぼ目的は達しられるのですが
> 何か手はありますでしょうか?
>

文字コードの問題が残りますが、正規表現でタグを削除するのがいいでしょう
http://www.atmarkit.co.jp/fdotnet/dotnettips/585regexreplace/regexreplace.html
■No22066に返信(やじゅさんの記事)
> ■No22064に返信(ふろんさんの記事)
>>HTMLタグだけ削除できればほぼ目的は達しられるのですが
>>何か手はありますでしょうか?
>>
>
> 文字コードの問題が残りますが、正規表現でタグを削除するのがいいでしょう
> http://www.atmarkit.co.jp/fdotnet/dotnettips/585regexreplace/regexreplace.html

やじゅ様
ありがとうございます。
私も、正規表現は調べましたがよく理解できず試していませんでした。
お教えいただいたサンプルは、単純明快でこれならいけると思いTESTしましたが
ご指摘の通り、文字コードの問題で引っ掛かっています。WebBrowserコントロール
での読み込みは、特に意識せずやってURL抽出は簡単にできましたので。
Sleipnirでは文字化けもなく正常に日本語の表示ができていましたのですがここにきて参りました。
WebBrowserコントロール読み込み時にUnicode指定で正常表示の可能性はあるのでしょうか?
引き続きご教授願えればありがたいです。
 >ふろん
■No22067に返信(ふろんさんの記事)

C#だけど、参考になるかしらん。
検討違いだったらごめんなさい。
WebBrowserのDocumentTextが文字化けします。
http://dobon.net/vb/bbs/log3-24/14371.html
■No22068に返信(やじゅさんの記事)
> ■No22067に返信(ふろんさんの記事)
>
> C#だけど、参考になるかしらん。
> 検討違いだったらごめんなさい。
> WebBrowserのDocumentTextが文字化けします。
> http://dobon.net/vb/bbs/log3-24/14371.html

やじゅ 様
ご連絡ありがとうございます。
参考レス拝見しました
>”直接DocumentStreamを扱うことにより解決しました”
とありますので、可能性大のように思います。
これからTEST して見ます情報ありがとうございました。
今後ともよろしくお願いします。
by ふろん
■No22071に返信(ふろんさんの記事)
> ■No22068に返信(やじゅさんの記事)
>>■No22067に返信(ふろんさんの記事)
>>
>>C#だけど、参考になるかしらん。
>>検討違いだったらごめんなさい。
>>WebBrowserのDocumentTextが文字化けします。
>>http://dobon.net/vb/bbs/log3-24/14371.html
>
> やじゅ 様
> ご連絡ありがとうございます。
> 参考レス拝見しました
> >”直接DocumentStreamを扱うことにより解決しました”
> とありますので、可能性大のように思います。
> これからTEST して見ます情報ありがとうございました。
> 今後ともよろしくお願いします。
> by ふろん
>
>



ケースが違うかもしれませんが、ソースを書いておきます。

直接吐く場合(文字コードをそのまま吐き出す)
FileStream f = new FileStream("test1.txt", FileMode.Create);
byte[] fb = new byte[webBrowser1.DocumentStream.Length];
webBrowser1.DocumentStream.Read(fb, 0, (int).DocumentStream.Length);
f.Write(fb, 0, fb.Length);
f.Close();

文字コード変換(eucをsjisに)
Encoding enceuc = Encoding.GetEncoding("euc-jp");
Encoding encsjs = Encoding.GetEncoding("shift_jis");
byte[] beuc = new byte[webBrowser1.DocumentStream.Length];
webBrowser1.DocumentStream.Read(beuc, 0, (int)webBrowser1.DocumentStream.Length);
byte[] bsjs = Encoding.Convert(enceuc, encsjs, beuc);
FileStream f = new FileStream("test.txt", FileMode.Create);
f.Write(bsjs, 0, bsjs.Length);
f.Close();

//byte[]をstringにするとき
string s=encsjs.GetString(bsjs);

先日、やじゅ 様
よりお教えいただいた、上記のコードを.NETに変換し色々試行錯誤しているのですが、エラーの修正方法がどうも私の力量では解決できません。

何とか、日本語TEXTの取り込みをしたいのせすが更にアドバイスいただけましたらどなたかよろしくお願い申し上げます。
■No22092に返信(ふろんさんの記事)

ごめんなさい、休憩中なので、動作は未確認です。
コンパイルエラーにはならないと思う。

Imports System.IO

Dim f As FileStream
Dim fb() As Byte

f = New FileStream("test1.txt", FileMode.Create)

Dim buff(CInt(WebBrowser1.DocumentStream.Length - 1)) As Byte
WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
f.Write(fb, 0, fb.Length)
f.Close()

'文字コード変換(eucをsjisに)
Dim enceuc As System.Text.Encoding
Dim encsjs As System.Text.Encoding
Dim bsjs() As Byte

enceuc = Encoding.GetEncoding("euc-jp")
encsjs = Encoding.GetEncoding("shift_jis")

Dim beuc(CInt(WebBrowser1.DocumentStream.Length)) As Byte

WebBrowser1.DocumentStream.Read(beuc, 0, CInt(WebBrowser1.DocumentStream.Length))
bsjs = Encoding.Convert(enceuc, encsjs, beuc)
f = New FileStream("test.txt", System.IO.FileMode.Create)
f.Write(bsjs, 0, bsjs.Length)
f.Close()

'byte[]をstringにするとき
Dim s As String
s = encsjs.GetString(bsjs)
■No22098に返信(やじゅさんの記事)
> ■No22092に返信(ふろんさんの記事)
>
> ごめんなさい、休憩中なので、動作は未確認です。
> コンパイルエラーにはならないと思う。
>
> Imports System.IO
>
> Dim f As FileStream
> Dim fb() As Byte
>
> f = New FileStream("test1.txt", FileMode.Create)
>
> Dim buff(CInt(WebBrowser1.DocumentStream.Length - 1)) As Byte
> WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
> f.Write(fb, 0, fb.Length)
> f.Close()
>
> '文字コード変換(eucをsjisに)
> Dim enceuc As System.Text.Encoding
> Dim encsjs As System.Text.Encoding
> Dim bsjs() As Byte
>
> enceuc = Encoding.GetEncoding("euc-jp")
> encsjs = Encoding.GetEncoding("shift_jis")
>
> Dim beuc(CInt(WebBrowser1.DocumentStream.Length)) As Byte
>
> WebBrowser1.DocumentStream.Read(beuc, 0, CInt(WebBrowser1.DocumentStream.Length))
> bsjs = Encoding.Convert(enceuc, encsjs, beuc)
> f = New FileStream("test.txt", System.IO.FileMode.Create)
> f.Write(bsjs, 0, bsjs.Length)
> f.Close()
>
> 'byte[]をstringにするとき
> Dim s As String
> s = encsjs.GetString(bsjs)
>

やじゅ 様 わざわざサンプルコードまで作って頂いてありがとうございました。

早速TESTしたのですが

下記の Encoding の3カ所が 名前 ”Encoding は宣言されていません”とエラーになるので TOPで、Imports System.Text の宣言で回避できましたが、

Dim encsjs As System.Text.Encoding
Dim bsjs() As Byte

enceuc = Encoding.GetEncoding("euc-jp")
         ~~~~~~~~
encsjs = Encoding.GetEncoding("shift_jis")
~~~~~~~~
Dim beuc(CInt(WebBrowser1.DocumentStream.Length)) As Byte

WebBrowser1.DocumentStream.Read(beuc, 0, CInt(WebBrowser1.DocumentStream.Length))
bsjs = Encoding.Convert(enceuc, encsjs, beuc)
~~~~~~~~
f = New FileStream("test.txt", System.IO.FileMode.Create)
f.Write(bsjs, 0, bsjs.Length)
f.Close()

'byte[]をstringにするとき
Dim s As String
s = encsjs.GetString(bsjs)

今度は

Dim test1 As String

test1 = WebBrowser1.DocumentText '全HTML取得

f = New FileStream(test1, FileMode.Create)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
のところで、”パスに無効な文字が含まれています”のエラー発生

テストサイトはここどぼんのサイトで行っています。

あと一息のようなのですが、何か設定間違っているでしょか?
■No22099に返信(ふろんさんの記事)
> test1 = WebBrowser1.DocumentText '全HTML取得
>
> f = New FileStream(test1, FileMode.Create)
> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> のところで、”パスに無効な文字が含まれています”のエラー発生
>

そこは直しちゃ駄目、そこはファイル名が入るとこだから。
ふろんさんのやろうとしているのは、ファイル名のとこにWEBサイトの
内容をセットしようとしているから、変な文字があるっておこられてるのさ


このプログラムのやってることを理解しましょう!
"test1.txt"に一旦WEBサイトのソースリストを保存してます。
その後に"test1.txt"を読み込んで処理してます。
■No22100に返信(やじゅさんの記事)
> ■No22099に返信(ふろんさんの記事)
>> test1 = WebBrowser1.DocumentText '全HTML取得
>>
>> f = New FileStream(test1, FileMode.Create)
>> ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>>のところで、”パスに無効な文字が含まれています”のエラー発生
>>
>
> そこは直しちゃ駄目、そこはファイル名が入るとこだから。
> ふろんさんのやろうとしているのは、ファイル名のとこにWEBサイトの
> 内容をセットしようとしているから、変な文字があるっておこられてるのさ
>
>
> このプログラムのやってることを理解しましょう!
> "test1.txt"に一旦WEBサイトのソースリストを保存してます。
> その後に"test1.txt"を読み込んで処理してます。

あ〜〜そうなんですか 全く分かってない!!

でどぼんさんのチップおかりして

test1 = WebBrowser1.DocumentText '全HTML取得

'StreamWriterの初期化
'ファイルを上書きし、Shift JISで書き込む
'2番目のパラメータをTrueにすると、上書きせずにファイルの末尾に追加
Dim sw As New System.IO.StreamWriter("C:\Users\Pro07\Desktop\test1.txt", _
False, _
System.Text.Encoding.GetEncoding(932))
sw.Write(WebBrowser1.DocumentText)
'閉じる
sw.Close()

f = New FileStream("C:\Users\Pro07\Desktop\test1.txt", FileMode.Create)

Dim buff(CInt(WebBrowser1.DocumentStream.Length - 1)) As Byte
WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
f.Write(fb, 0, fb.Length)
f.Close()


やってみたのですが
バッファは null にはできません。のエラーです
パラメータ名: buffer

保存モードが悪いのでしょうか?
> バッファは null にはできません。のエラーです
> パラメータ名: buffer
元のサンプルに間違いがあるので、探して下さい。

** 考え方・解決に至るまでのプロセス **
1.どこの行でそのエラーが出るかから、どの変数がnullになっているかを確かめる。
2.そこには何が入るべきか考える(今回の場合は確保された配列です)
3.適切に修正する



-----
今回の場合は取り違えですね。
■No22102に返信(Azuleanさんの記事)
>>バッファは null にはできません。のエラーです
>>パラメータ名: buffer
> 元のサンプルに間違いがあるので、探して下さい。
>
> ** 考え方・解決に至るまでのプロセス **
> 1.どこの行でそのエラーが出るかから、どの変数がnullになっているかを確かめる。
> 2.そこには何が入るべきか考える(今回の場合は確保された配列です)
> 3.適切に修正する
>
>
>
> -----
> 今回の場合は取り違えですね。

Azuleanさん
ご助言ありがとうございます。
う〜〜む元サンプルに問題ありき? なんですか
ご指摘いただいた、ヒントでがんばってみます
■No22103に返信(ふろんさんの記事)
> ■No22102に返信(Azuleanさんの記事)
> >>バッファは null にはできません。のエラーです
> >>パラメータ名: buffer
>>元のサンプルに間違いがあるので、探して下さい。
>>
>>** 考え方・解決に至るまでのプロセス **
>>1.どこの行でそのエラーが出るかから、どの変数がnullになっているかを確かめる。
>>2.そこには何が入るべきか考える(今回の場合は確保された配列です)
>>3.適切に修正する
>>
>>
>>
>>-----
>>今回の場合は取り違えですね。
>
> Azuleanさん
> ご助言ありがとうございます。
> う〜〜む元サンプルに問題ありき? なんですか
> ご指摘いただいた、ヒントでがんばってみます
>

'CInt 関数指定 された式をバリアント型
 (内部処理形式が整数型 (Integer) の Variant) に変換して返します。

'----------------------------------------------------------
' Dim buff(WebBrowser1.DocumentStream.Length - 1) As Byte
' WebBrowser1.DocumentStream.Read(buff, 0,       WebBrowser1.DocumentStream.Length)
' Me.TextBox2.Text = System.Text.Encoding.GetEncoding(WebBrowser1.Document.Encoding).GetString(buff)

'-----------------------------------------------------------

WebBrowserでの処理経験がほとんどなく、各コマンドの機能を調べていましたら
上記のサンプルを発見し、これでみごと日本文字の取得に成功しました!!

違いは、
配列宣言はbuffなのに、bfで指定されてること ← ミスコード

WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))

コードにある CInt関数の使用の意味は今一理解できません。

しかし、これで文字コード変換ロジックを通さなくても正常に取得できています
(全てのサイトは未検証)

まだまだ、このあたりのロジックは完全に理解できていませんが
やっと念願の日本文字取得ができました。

これから正規表現で不要なHTMLタグ削除をやってみます。

貴重なご意見、指導を頂いた、

Azulean様 やじゅ 様
本当にありがとうございました。
厚く感謝申し上げます。
今後ともよろしくお願い申し上げます。

by ふろん
> 違いは、
> 配列宣言はbuffなのに、bfで指定されてること ← ミスコード
細かいことですが、bfじゃなくてfbですね。
"F"ile"B"ufferの略かと思われます。

> WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
> コードにある CInt関数の使用の意味は今一理解できません。
DocumentStreamプロパティはStreamクラスのインスタンスを返します。
http://msdn.microsoft.com/ja-jp/library/system.windows.forms.webbrowser.documentstream.aspx

StreamクラスのLengthプロパティはLong型の数値を返します。
http://msdn.microsoft.com/ja-jp/library/system.io.stream.length.aspx

しかし、StreamクラスのReadの第3引数はInteger型で要求されているので、CInt関数でLong型をInteger型に変えているのです。
http://msdn.microsoft.com/ja-jp/library/system.io.stream.read.aspx

VBではCInt関数を省略してもコンパイルエラーにならないのかもしれませんが、念のため型を揃えると言った意図かと考えられます。


> しかし、これで文字コード変換ロジックを通さなくても正常に取得できています
> (全てのサイトは未検証)
文字コードは結構多いですから、多分通らないところもあるんじゃないかなぁと思っています。
#コードの意図するところを厳密に読んでいないので、私の考えは外しているかもしれません。
■No22105に返信(Azuleanさんの記事)
>>違いは、
>>配列宣言はbuffなのに、bfで指定されてること ← ミスコード
> 細かいことですが、bfじゃなくてfbですね。
> "F"ile"B"ufferの略かと思われます。
>
>>WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
>>コードにある CInt関数の使用の意味は今一理解できません。
> DocumentStreamプロパティはStreamクラスのインスタンスを返します。
> http://msdn.microsoft.com/ja-jp/library/system.windows.forms.webbrowser.documentstream.aspx
>
> StreamクラスのLengthプロパティはLong型の数値を返します。
> http://msdn.microsoft.com/ja-jp/library/system.io.stream.length.aspx
>
> しかし、StreamクラスのReadの第3引数はInteger型で要求されているので、CInt関数でLong型をInteger型に変えているのです。
> http://msdn.microsoft.com/ja-jp/library/system.io.stream.read.aspx
>
> VBではCInt関数を省略してもコンパイルエラーにならないのかもしれませんが、念のため型を揃えると言った意図かと考えられます。
>
>
>>しかし、これで文字コード変換ロジックを通さなくても正常に取得できています
>>(全てのサイトは未検証)
> 文字コードは結構多いですから、多分通らないところもあるんじゃないかなぁと思っています。
> #コードの意図するところを厳密に読んでいないので、私の考えは外しているかもしれません。

Azulean 様
詳細な解説ありがとうございます。
私も、CInt関数を除いても変換できていましたので、これの目的がよく理解
できていませんでした。
>文字コード変換ロジック
は念のため通しています。

この辺りをよく理解していないと、何かあった場合応用か利きませんね。
よく勉強しておきます。

レス頂ながらご返事遅れ申し訳ございません
今正規表現をつついています、こちらのほうは一発で不要タグの削除に成功しました、やってみてこんな便利なコマンドに驚いています。
使い方次第ではTEXTの成型加工に威力が発揮できそうです。
今、色々なパターンで実験中です。
色々ご教示頂きありがとうございました。
感謝申し上げ、解決とさせていただきます。
by ふろん
■No22106に返信(ふろんさんの記事)
> ■No22105に返信(Azuleanさんの記事)
> >>違いは、
> >>配列宣言はbuffなのに、bfで指定されてること ← ミスコード
>>細かいことですが、bfじゃなくてfbですね。
>>"F"ile"B"ufferの略かと思われます。
>>
> >>WebBrowser1.DocumentStream.Read(fb, 0, CInt(WebBrowser1.DocumentStream.Length))
> >>コードにある CInt関数の使用の意味は今一理解できません。
>>DocumentStreamプロパティはStreamクラスのインスタンスを返します。
>>http://msdn.microsoft.com/ja-jp/library/system.windows.forms.webbrowser.documentstream.aspx
>>
>>StreamクラスのLengthプロパティはLong型の数値を返します。
>>http://msdn.microsoft.com/ja-jp/library/system.io.stream.length.aspx
>>
>>しかし、StreamクラスのReadの第3引数はInteger型で要求されているので、CInt関数でLong型をInteger型に変えているのです。
>>http://msdn.microsoft.com/ja-jp/library/system.io.stream.read.aspx
>>
>>VBではCInt関数を省略してもコンパイルエラーにならないのかもしれませんが、念のため型を揃えると言った意図かと考えられます。
>>
>>
> >>しかし、これで文字コード変換ロジックを通さなくても正常に取得できています
> >>(全てのサイトは未検証)
>>文字コードは結構多いですから、多分通らないところもあるんじゃないかなぁと思っています。
>>#コードの意図するところを厳密に読んでいないので、私の考えは外しているかもしれません。
>
> Azulean 様
> 詳細な解説ありがとうございます。
> 私も、CInt関数を除いても変換できていましたので、これの目的がよく理解
> できていませんでした。
> >文字コード変換ロジック
> は念のため通しています。
>
> この辺りをよく理解していないと、何かあった場合応用か利きませんね。
> よく勉強しておきます。
>
> レス頂ながらご返事遅れ申し訳ございません
> 今正規表現をつついています、こちらのほうは一発で不要タグの削除に成功しました、やってみてこんな便利なコマンドに驚いています。
> 使い方次第ではTEXTの成型加工に威力が発揮できそうです。
> 今、色々なパターンで実験中です。
> 色々ご教示頂きありがとうございました。
> 感謝申し上げ、解決とさせていただきます。
> by ふろん
>
>
>
解決のチェツク入れ忘れ
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板