0
  1. 一般に、HTML で正規表現を使用するべきではないことはわかっています。一定のパターンを持つファイルからデータをすばやく取り除くための 1 回限りのツールとして使用しており、二度と使用することはありません。このタスクには正規表現を使用したいと考えています。HTML を Regex で解析すべきではないことを理解しています。
  2. いいえ、XML パーサー、BeautifulSoup、lxml などは使いたくありません。ありがとうございます。:)
  3. 私はこれを 1 回だけ使用して、永遠に使用したいと考えています。

そうは言っても、私が書いた正規表現は、ファイルの最後の「一致」にのみ一致します。理由はわかりません。ファイルにはかなり一定のパターンがあります。

<p someAttribute="yes"><b someOtherAttribute="no">My Title - </b> My Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 2nd Title - </b> My 2nd Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 3rd Title - </b> My 3rd Description</p>
<p class="normal" style="margin-left:1"><b style="font-weight:400">Another one </b>The cake is a lie</p>

属性は気にしません。<b>タグに含まれるものとそれに続くものをグループ化しようとしています。タイトルと説明。

def parseData(html):
    pattern = re.compile('.*<p.*><b.*>(.+)</b>(.+)</p>.*')

    matches = re.findall(pattern, str(html))

    for match in matches:
        print(match)

def main():
    htmlFile = "myFile.htm"

    browser = UrlBrowser()

    parseData(browser.getHTML(htmlFile))

このパターンは、利用可能な最後の「一致」にのみ一致します.*。それが問題になるかどうかを確認するために before を追加しようとしましたが、違いはありませんでした。正規表現で何が欠けていますか?

4

3 に答える 3

2

これでうまくいくはずです。この動作デモを見る

matches = re.findall(r'<b[^>]+>(.*?)</b>(.*?)</p>', str)

正規表現:

<b            match start of tag '<b'
 [^>]+        any character except: '>' (1 or more times)
 >            match enclosed '>'
 (            group and capture to \1:
  .*?         any character except \n (0 or more times)
 )            end of \1
 </b>         match '</b>'
 (            group and capture to \2:
  .*?         any character except \n (0 or more times)
 )            end of \2
 </p>         match '</p>'

あなた.*は貪欲な(可能な限り多くの量を一致させる)ものを使用しています。その最後に追加して、貪欲でないようにしたい?(可能な限り最小限の量に一致する)

re次の量指定子?+?、について説明しているドキュメントから説明を得る??

*、「+」、および「?」修飾子はすべて貪欲です。可能な限り多くのテキストに一致します。この動作が望ましくない場合もあります。RE < の場合。> は '<H1>title</H1>' と一致し、'<H1>' だけでなく、文字列全体と一致します。「?」の追加 修飾子が非貪欲または最小限の方法で一致を実行させた後。できるだけ少ない文字が一致します。を使用します。? 前の式の '<H1>' のみに一致します。

于 2013-09-24T13:49:22.647 に答える
1

最後の一致を引き起こしているのは、先頭の .* です。* および + 修飾子は、一致を生成しながら、前の項目のできるだけ多くに一致します

「貪欲でない」*を使用しますか?各 * の代わりに +? 各 + の代わりに、一致を生成する可能な限り短いシーケンスを取得します。

参照: http://docs.python.org/3.3/library/re.html#regular-expression-syntax

于 2013-09-24T13:37:56.890 に答える
0

さらに何かが起こっています。

import re

data = """\
<p someAttribute="yes"><b someOtherAttribute="no">My Title - </b> My Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 2nd Title - </b> My 2nd Description</p>
<p someAttribute="yes"><b someOtherAttribute="no">My 3rd Title - </b> My 3rd Description</p>
<p class="normal" style="margin-left:1"><b style="font-weight:400">Another one </b>The cake is a lie</p>"""

print(*re.findall('.*<p.*><b.*>(.+)</b>(.+)</p>.*', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')

.*最初と最後には必要ないことに注意してください。

print(*re.findall('<p.*><b.*>(.+)</b>(.+)</p>', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')

正規表現はすでに文字列全体を検索して一致するためです。

貪欲でない繰り返しを好むかもしれませんが、それが問題だとは思いません:

print(*re.findall('<p.*?><b.*?>(.+?)</b>(.+?)</p>', data), sep="\n")
#>>> ('My Title - ', ' My Description')
#>>> ('My 2nd Title - ', ' My 2nd Description')
#>>> ('My 3rd Title - ', ' My 3rd Description')
#>>> ('Another one ', 'The cake is a lie')
于 2013-09-24T13:46:26.773 に答える