Python RegExは最初の数文字をスキップしますか?
-
06-07-2019 - |
質問
ちょっと正規表現についてはかなり基本的な質問があります。 bodyタグ内(および含む)のテキストを返すだけです。bodyタグを開く前のすべての文字にも一致するため、以下は正しくないことがわかります。それらをスキップするにはどうすればいいのだろうか?
x = re.match('(.*<body).*?(</body>)', fileString)
ありがとう!
解決
<body>...</body>
タグ間のすべてのテキストを見つけるために正規表現を使用するコードの例を次に示します。これはpythonのreモジュールのいくつかの機能を示していますが、 Beautiful Soup モジュールは非常に使いやすく、HTMLまたはXMLの解析を計画している場合に使用するのに適したツールです。 (BeautifulSoupを使用してこれを解析する方法の例については、以下を参照してください。)
#!/usr/bin/env python
import re
# Here we have a string with a multiline <body>...</body>
fileString='''baz<body>foo
baby foo
baby foo
baby foo
</body><body>bar</body>'''
# re.DOTALL tells re that '.' should match any character, including newlines.
x = re.search('(<body>.*?</body>)', fileString, re.DOTALL)
for match in x.groups():
print(match)
# <body>foo
# baby foo
# baby foo
# baby foo
# </body>
すべての一致を収集する場合は、re.findallを使用できます。
print(re.findall('(<body>.*?</body>)', fileString, re.DOTALL))
# ['<body>foo\nbaby foo\nbaby foo\nbaby foo\n</body>', '<body>bar</body>']
また、このパターンを複数回使用する場合は、プリコンパイルできます:
pat=re.compile('(<body>.*?</body>)', re.DOTALL)
print(pat.findall(fileString))
# ['<body>foo\nbaby foo\nbaby foo\nbaby foo\n</body>', '<body>bar</body>']
そして、BeautifulSoupでこれを行う方法を次に示します。
#!/usr/bin/env python
from BeautifulSoup import BeautifulSoup
fileString='''baz<body>foo
baby foo
baby foo
baby foo
</body><body>bar</body>'''
soup = BeautifulSoup(fileString)
print(soup.body)
# <body>foo
# baby foo
# baby foo
# baby foo
# </body>
print(soup.findAll('body'))
# [<body>foo
# baby foo
# baby foo
# baby foo
# </body>, <body>bar</body>]
他のヒント
Pythonについては知りませんが、 Beautiful Soup 、Python HTML解析に推奨されることがよくあります。
import BeautifulSoup
soup = BeautifulSoup(fileString)
bodyTag = soup.html.body.string
(理論的には)HTMLのすべての複雑さを処理します。純粋な正規表現ベースの回答では非常に困難です。正規表現が設計されたものではないためです。
正規表現を使用してHTMLを解析することはできません。 HTMLは通常の言語ではありません。代わりにlxmlなどのHTMLパーサーを使用してください。
x = re.match('.*(<body>.*?</body>)', fileString)
HTML解析のミニマムを考慮してください。
x = re.search('(<body>.*</body>)', fileString)
x.group(1)
一致する回答よりも入力が少ない
fileStringには複数行が含まれていますか?その場合、指定するか、明示的に行をスキップする必要がある場合があります。
x = re.match(r"(?:.|\n)*(<body>(?:.|\n)*</body>)", fileString)
または、より簡単にreモジュールを使用:
x = re.match(r".*(<body>.*</body>)", fileString, re.DOTALL)
xがNoneでない場合、 x.groups()[0]
に文字列を含める必要があります。