2017-04-07 18 views
1

私はPython 2.7.3とbsを持っています。Python BeautifulSoupがfind_all()から入力の間違ったリストを返す

input:<input name="fname" type="text"> 
<input name="email" type="text"> 
<input name="Submit" type="button" value="submit"> 
</input></input></input> 
input:<input name="email" type="text"> 
<input name="Submit" type="button" value="submit"> 
</input></input> 
input:<input name="Submit" type="button" value="submit"> 
</input> 

何が起こった

input: <input name="fname" type="text"> 
input: <input type="text" name="email"> 
input: <input type="button" name="Submit" value="submit"> 

を返すことになっています:バージョンは、このコード

from bs4 import BeautifulSoup # parsing 

html = """ 
<html> 
<head id="Head1"><title>Title</title></head> 
<body> 
    <form id="form" action="login.php" method="post"> 
     <input type="text" name="fname"> 
     <input type="text" name="email" > 
     <input type="button" name="Submit" value="submit"> 
    </form> 
</body> 

</html> 
""" 

html_proc = BeautifulSoup(html, 'html.parser') 

for form in html_proc.find_all('form'): 
    for input in form.find_all('input'): 
     print "input:" + str(input) 

は、入力の間違ったリストを返すいくつかの理由4.4.1

です?

答えて

2

私にとって、これは、HTMLパーサのアーティファクトのように見えます。 'html.parser'の代わりに'lxml'をパーサーに使用すると、問題なく動作しているようです。これの欠点は、あなた(またはあなたのユーザー)がインストールする必要があるということです。lxml - 有益な点は、lxmlがより良い/より速いパーサーであることです;-)。'html.parser'、この場合には正しく動作するようには思えない理由

については、私はそれがinputタグが自動閉鎖しているという事実とは何かを持っていると思います。あなたが明示的にあなたの入力を閉じた場合、それが動作します:

<input type="text" name="fname" ></input> 
<input type="text" name="email" ></input> 
<input type="button" name="Submit" value="submit" ></input> 

私たちは、このケースを処理するために、ソースコードを変更することができるかどうかを確認する好奇心だろう...モンキーパッチに少し実験を行うbs4は、我々を示し、これを行うことができます。

from bs4 import BeautifulSoup 

from bs4.builder import _htmlparser 

# Monkey-patch the Beautiful soup HTML parser to close input tags automatically. 
BeautifulSoupHTMLParser = _htmlparser.BeautifulSoupHTMLParser 
class FixedParser(BeautifulSoupHTMLParser): 
    def handle_starttag(self, name, attrs): 
     # Old-style class... No super :-(
     result = BeautifulSoupHTMLParser.handle_starttag(self, name, attrs) 
     if name.lower() == 'input': 
      self.handle_endtag(name) 
     return result 

_htmlparser.BeautifulSoupHTMLParser = FixedParser 


html = """ 
<html> 
<head id="Head1"><title>Title</title></head> 
<body> 
    <form id="form" action="login.php" method="post"> 
     <input type="text" name="fname" > 
     <input type="text" name="email" > 
     <input type="button" name="Submit" value="submit" > 
    </form> 
</body> 

</html> 
""" 

html_proc = BeautifulSoup(html, 'html.parser') 

for form in html_proc.find_all('form'): 
    for input in form.find_all('input'): 
     print "input:" + str(input) 

明らかに、これは修正ではありません(私はBS4の人々へのパッチとしてこれを提出していないだろう)が、それは、問題を示しません。終了タグがないので、handle_endtagメソッドが呼び出されることはありません。私たちがそれを自分自身と呼ぶと、物事はうまくいかない(HTMLがでもに閉じ入力タグがある限り...)。

私は本当にこのバグが誰になるのか分かりませんが、あなたはbs4にそれを提出することで始めることができると思います - 彼らはあなたに転送して、Pythonトラッカーのバグを報告するかもしれません。確かに...

+0

ありがとうございました。これは機能します。私はで入力を終了しなければならないのは奇妙なことです。標準HTMLコードではないからです。 https://www.w3schools.com/tags/tag_input.asp誰かがこれを適切な人に報告できるのであれば、それは大歓迎です。 – Arrow

+0

@Arrow - バグを報告することから始めます。https://bugs.launchpad.net/beautifulsoup/ – mgilson

0

は、このためにネストされたループを使用しlxmlを使用し、これにあなたのコードを変更しないでください:

inp = [] 
html_proc = BeautifulSoup(html, 'lxml') 

for form in html_proc.find_all('form'): 
    inp.extend(form.find_all('input')) 

for item in inp:  
    print "input:" + str(item) 
関連する問題