4

ここで少し脳がフリーズするので、いくつかのポインターを期待していました。基本的に、特定の div タグのコンテンツを抽出する必要があります。はい、正規表現は通常、これに対して承認されていないことを知っていますが、単純な Web スクレイピング アプリケーションであり、ネストされた div はありません。

私はこれを一致させようとしています:

    <div class="entry">
  <span class="title">Some company</span>
  <span class="description">
  <strong>Address: </strong>Some address
    <br /><strong>Telephone: </strong> 01908 12345
  </span>
</div>

簡単な vb コードは次のとおりです。

    Dim myMatches As MatchCollection
    Dim myRegex As New Regex("<div.*?class=""entry"".*?>.*</div>", RegexOptions.Singleline)
    Dim wc As New WebClient
    Dim html As String = wc.DownloadString("http://somewebaddress.com")
    RichTextBox1.Text = html
    myMatches = myRegex.Matches(html)
    MsgBox(html)
    'Search for all the words in a string
    Dim successfulMatch As Match
    For Each successfulMatch In myMatches
        MsgBox(successfulMatch.Groups(1).ToString)
    Next

どんな助けでも大歓迎です。

4

4 に答える 4

8

あなたの正規表現はあなたの例のために働きます。ただし、行う必要のある改善点がいくつかあります。

<div[^<>]*class="entry"[^<>]*>(?<content>.*?)</div>

[^<>]*「山かっこを除く任意の数の文字に一致する」という意味で、現在のタグから誤って抜け出さないようにします。

.*??)は、「任意の数の文字に一致しますが、可能な限り少ない文字に一致する」ことを意味します。これにより、ページの最初のタグから最後のタグへの一致が回避さ<div class="entry">れます。

しかし、正規表現自体はまだ何かと一致しているはずです。おそらくあなたはそれを正しく使用していませんか?

Visual Basicがわからないので、これは暗闇の中でのショットですが、RegexBuddyは次のアプローチを提案しています。

Dim RegexObj As New Regex("<div[^<>]*class=""entry""[^<>]*>(?<content>.*?)</div>")
Dim MatchResult As Match = RegexObj.Match(SubjectString)
While MatchResult.Success
    ResultList.Add(MatchResult.Groups("content").Value)
    MatchResult = MatchResult.NextMatch()
End While

これ以上の正規表現アプローチを採用しないことをお勧めします。主張すると、次のようなモンスターの正規表現になります。これは、divの内容の形式が決して変化しない場合にのみ機能します。

<div[^<>]*class="entry"[^<>]*>\s*
<span[^<>]*class="title"[^<>]*>\s*
(?<title>.*?)
\s*</span>\s*
<span[^<>]*class="description"[^<>]*>\s*
<strong>\s*Address:\s*</strong>\s*
(?<address>.*?)
\s*<strong>\s*Telephone:\s*</strong>\s*
(?<phone>.*?)
\s*</span>\s*</div>

または(VB.NETの複数行の文字列の喜びを見てください):

Dim RegexObj As New Regex(
    "<div[^<>]*class=""entry""[^<>]*>\s*" & chr(10) & _
    "<span[^<>]*class=""title""[^<>]*>\s*" & chr(10) & _
    "(?<title>.*?)" & chr(10) & _
    "\s*</span>\s*" & chr(10) & _
    "<span[^<>]*class=""description""[^<>]*>\s*" & chr(10) & _
    "<strong>\s*Address:\s*</strong>\s*" & chr(10) & _
    "(?<address>.*?)" & chr(10) & _
    "\s*<strong>\s*Telephone:\s*</strong>\s*" & chr(10) & _
    "(?<phone>.*?)" & chr(10) & _
    "\s*</span>\s*</div>", 
    RegexOptions.Singleline Or RegexOptions.IgnorePatternWhitespace)

(もちろん、結果を保存する必要がありますMatchResult.Groups("title")...)

于 2012-07-03T08:01:39.733 に答える
2

RegexOptions.Multilineの代わりに使用してみてくださいRegexOptions.Singleline

上記が機能しないことを指摘してくれた@Timに感謝します...私の悪い。

@Timの答えは良いものであり、受け入れられるはずですが、コードの動作を妨げている余分な部分は、Group(1)返すための2番目のグループがないことです。

変化する...

MsgBox(successfulMatch.Groups(1).ToString)

に...

MsgBox(successfulMatch.Groups(0).ToString)
于 2012-07-03T07:50:09.883 に答える
0

これを使う

<div.*?class=""entry"".*?>(?<divBody>.*)</div>

divBodyという名前のグループを取得します

ただし、文字列に他のノードdivが含まれている場合はこれが機能しないことに注意してください(正規表現でこれを解決する方法がないようです)。あなたのソリューションにはxsltが役立つかもしれません。

于 2012-07-03T07:59:10.877 に答える