2012-02-21 7 views
2

私はHTMLの点で次のようなことをしています。私の最初の衝動だった消費のためにxpathを使用して表のセルのテキストコンテンツを抽出していますか?

<p align="center"> 
    <img src="some_image.gif" alt="Some Title"> 
</p> 
<TABLE WIDTH=500 BORDER=1 class=textwhite ALIGN=center CELLPADDING=0 CELLSPACING=0> 
<TR> 
<TD colspan=4 ALIGN=center><b>Title</b></TD> 
</TR> 
<TR> 
<TD ALIGN=center>Title</TD> 
<TD ALIGN=center>date</TD> 
<TD ALIGN=center>value</TD> 
<TD ALIGN=center>value</TD> 
</TR><TR> 
    <TD ALIGN=center>Title2</TD> 
    <TD ALIGN=center></TD> 
    <TD ALIGN=center><div class=redtext>----</div></TD> 
    <TD>&nbsp;</TD> 
</TR><TR> 
    <TD ALIGN=center>Title3</TD> 
    <TD ALIGN=center><div class=yellowtext>value</div></TD> 
    <TD ALIGN=center><div class=redtext>value</div></TD> 
    <TD ALIGN=center>value<SUP>6</SUP></TD> 
</TR><TR> 
    <TD ALIGN=center>Title4</TD> 
    <TD ALIGN=center><div class=bluetext>value</div></TD> 
    <TD ALIGN=center><div class=redtext>value</div></TD> 
    <TD>&nbsp;</TD> 
</TR></TABLE> 

<blockquote> 
    <p class="textstyle"> 
     Text. 
    </p> 
</blockquote> 

:私はテーブルセルの様々なコンテンツを抽出したいと思います、しかし、私はいくつかの組み込みのdivは、細胞内で時折あることを発見し、私はまだのわからないんだけど、おそらく他の奇妙すべての要素テキストを抽出し、プログラムでそれをスライスします。 Title1、Title2などで行が始まるときを知り、 "----"が値なしを意味すると見なされたら、この行をスキップして移動します。しかし、おそらくこれをxpathで直接処理するより良い方法があることに気付きました。

どのようにしてxpathを使って解決すれば、各セルの最終的な子供のテキストコンテンツが存在する場合、各divに入る必要がありますか?または、これに近づくようなより多くのxpathがありますか?

明らかに、他の予期しない要素が発生しても、脆弱ではない最も柔軟なソリューションを試しています。

+1

なぜ希望の出力を教えてください。 – pguardiario

+0

希望の出力は、単に各セルの内容です。最終的に、これは、 "Title1"、 "Title2"などが各ハッシュの名前になるようにハッシュの配列に格納されます。次に、行に続く各セルに値がある場合、そのハッシュの追加値になります。 – ylluminate

答えて

3

提供されたテキストは、したがって、整形式のXML文書ではありませんXPathは適用されません

あなたであれば正しいと、このような式が有用であるかもしれない、以下の一つとして整形式のXML文書にそれをひそか:

/*/TABLE//TD//text() 

かさえ:

//TABLE//TD//text() 

提供されたHTMLから構築された適切なXMLドキュメントを次に示します。

<html> 
    <p align="center"> 
     <img src="some_image.gif" alt="Some Title"/> 
    </p> 
    <TABLE WIDTH="500" BORDER="1" class="textwhite" ALIGN="center" CELLPADDING="0" CELLSPACING="0"> 
     <TR> 
      <TD colspan="4" ALIGN="center"> 
       <b>Title</b> 
      </TD> 
     </TR> 
     <TR> 
      <TD ALIGN="center">Title</TD> 
      <TD ALIGN="center">date</TD> 
      <TD ALIGN="center">value</TD> 
      <TD ALIGN="center">value</TD> 
     </TR> 
     <TR> 
      <TD ALIGN="center">Title2</TD> 
      <TD ALIGN="center"></TD> 
      <TD ALIGN="center"> 
       <div class="redtext">----</div> 
      </TD> 
      <TD>&#xA0;</TD> 
     </TR> 
     <TR> 
      <TD ALIGN="center">Title3</TD> 
      <TD ALIGN="center"> 
       <div class="yellowtext">value</div> 
      </TD> 
      <TD ALIGN="center"> 
       <div class="redtext">value</div> 
      </TD> 
      <TD ALIGN="center">value 
       <SUP>6</SUP> 
      </TD> 
     </TR> 
     <TR> 
      <TD ALIGN="center">Title4</TD> 
      <TD ALIGN="center"> 
       <div class="bluetext">value</div> 
      </TD> 
      <TD ALIGN="center"> 
       <div class="redtext">value</div> 
      </TD> 
      <TD>&#xA0;</TD> 
     </TR> 
    </TABLE> 
    <blockquote> 
     <p class="textstyle">   Text.  </p> 
    </blockquote> 
</html> 
どのような「タイトル」が変化した場合場合、またはタイプミスがある - 10
+0

ここのキーは// text()です。ありがとう。 – ylluminate

+0

@yluminate:どうぞよろしくお願いいたします。 –

0

ので、多分、私は非常にお勧めされ、あなたがdivを歩くことをしたくないが、ここで私の解決策は、lxmlのを使用している:

import re 
from cStringIO import StringIO 
from lxml import etree 

def getTable(html, table_xpath, rows_xpath, cells_xpath): 
    """Get a table on a webpage""" 
    parser = etree.HTMLParser() 
    # Build document tree and get table 
    root = etree.parse(StringIO(html), parser) 
    table = root.find(table_xpath) 
    if table == None: 
     print 'No table.' 
     return [] 
    rows = table.findall(rows_xpath) 
    document = [] 
    def cleanText(text): 
     """Clean up text by replacing line breaks and tabs. """ 
     return re.sub(r'[\r\n\t]+','',str(text).strip()) 
    # iterate over the table rows and collect text from each cell. 
    for r in rows: 
     cells = r.findall(cells_xpath) 
     rowdata = [] 
     for c in cells: 
      text = '' 
      it = c.itertext() 
      for i in it: 
       text += cleanText(i) + ' ' 
      rowdata.append(text) 
     document.append(rowdata) 
    return document 


html = """ 
<html><head><title></title></head><body> 
<p align="center"> 
    <img src="some_image.gif" alt="Some Title"> 
    </p> 
    <TABLE WIDTH=500 BORDER=1 class=textwhite ALIGN=center CELLPADDING=0 CELLSPACING=0> 
    <TR> 
    <TD colspan=4 ALIGN=center><b>Title</b></TD> 
    </TR> 
    <TR> 
    <TD ALIGN=center>Title</TD> 
    <TD ALIGN=center>date</TD> 
    <TD ALIGN=center>value</TD> 
    <TD ALIGN=center>value</TD> 
    </TR><TR> 
    <TD ALIGN=center>Title2</TD> 
    <TD ALIGN=center></TD> 
    <TD ALIGN=center><div class=redtext>----</div></TD> 
    <TD>&nbsp;</TD> 
    </TR><TR> 
    <TD ALIGN=center>Title3</TD> 
    <TD ALIGN=center><div class=yellowtext>value</div></TD> 
    <TD ALIGN=center><div class=redtext>value</div></TD> 
    <TD ALIGN=center>value<SUP>6</SUP></TD> 
    </TR><TR> 
    <TD ALIGN=center>Title4</TD> 
    <TD ALIGN=center><div class=bluetext>value</div></TD> 
    <TD ALIGN=center><div class=redtext>value</div></TD> 
    <TD>&nbsp;</TD> 
</TR></TABLE> 
</body> 
</html> 
""" 
tp = "//table[@width='500']" 
rt = "tr" 
cp = "td[@align='center']" 

doc = getTable(html, tp, rt, cp) 
print repr(doc) 
0

私はあなたのプログラムは、入力データが操作されると、多くの問題に実行しようとしていることを信じますか?彼らは予告なくで完全にすべてを変えることができるよう

それは、他の誰かのウェブサイトをスクレイピングに厳密解を作ることは本当に不可能です。少なくとも出力が正常であることを検証しようとする、耐性のある柔軟なコードを書く方が良いでしょう。この場合、それは、このループ内で、「//テーブル/ TR」の結果を反復処理するために、おそらく最善です、プロセスのtd要素:

import lxml.etree 
tree = lxml.etree.fromstring("<table><tr><td>test</td></tr><tr><td><div>test2</div></td></tr></table>") 
stringify = lambda x : "".join(x.xpath(".//text()")) 
for x in tree.xpath("//table/tr"): 
    print "New row" 
    for y in x.xpath("td"): 
     print stringify(y) 

出力:

New row 
test 
New row 
test2 

次のコードでしょう

print map(stringify, tree.xpath("//table/tr/td")) 

出力:

['test', 'test2'] 
、しかし、あなたが求めるリストを取得10

これがすべてで順番にテーブルの直接の子孫であるTRの直接の子孫であるtdから派生しているすべてのテキスト要素を見つけます。

( "< TD>はFoo < B>バー</B> </TD>" または類似が含まれているHTML上で実行したときに単純にすべてのテキスト()の要素を求めることはいくつかの面白いバグが作成されます。)

関連する問題