1

次のコードを使用して、この質問の最後にある出力からいくつかのフィールドを抽出しようとしています。

doc = LH.fromstring(html2)
tds = (td.text_content() for td in doc.xpath("//td[not(*)]"))

for a,b,c in zip(*[tds]*3):
    print (a,b,c)

私が期待しているのは、notificationNodeName、notificationNodeName、packageName、notificationEnabledの各フィールドのみを抽出することです。

それに関する主な問題は、結果をデータベースに入れたいからです。そして私は代わりに受け取る必要があります:

実際のコードは次を返します:

('JDBCAdapter', 'JDBCAdapter', 'Package:Notif')
('Package', 'yes', 'Package_2:Notif')
('Package_2', 'yes')

必要なもの:

('Package:Notif','Package', 'yes')
('Package_2:Notif','Package_2', 'yes')

私が見つけた手に負えない解決策は次のとおりです。

doc = LH.fromstring(html2)
tds = (td.text_content() for td in doc.xpath("//td"))

for td, val in zip(*[tds]*2):
    if td == 'notificationNodeName':
        notificationNodeName = val
    elif td == 'packageName':
        packageName = val
    elif td == 'notificationEnabled':
        notificationEnabled = val
        print (notificationNodeName,packageName,notificationEnabled)

それは機能しますが、私には正しく見えません。それを行うためのより良い方法になると確信しています。

元のHTML出力:

<tbody><tr>
<td valign="top"><b>adapterTypeName</b></td>
<td>JDBCAdapter</td>
</tr>
<tr>
<td valign="top"><b>adapterTypeNameList</b></td>
<td>
<table>
<tbody><tr>
<td>JDBCAdapter</td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td valign="top"><b>notificationDataList</b></td>
<td>
<table>
<tbody><tr>
<td><table bgcolor="#dddddd" border="1">
<tbody><tr>
<td valign="top"><b>notificationNodeName</b></td>
<td>package:Notif</td>
</tr>
<tr>
<td valign="top"><b>packageName</b></td>
<td>Package</td>
</tr>
<tr>
<td valign="top"><b>notificationEnabled</b></td>
<td>unsched</td>
</tr>
</tbody></table>
</td>
</tr>
<tr>
<td><table bgcolor="#dddddd" border="1">
<tbody><tr>
<td valign="top"><b>notificationNodeName</b></td>
<td>Package_2:notif</td>
</tr>
<tr>
<td valign="top"><b>packageName</b></td>
<td>package_2</td>
</tr>
<tr>
<td valign="top"><b>notificationEnabled</b></td>
<td>yes</td>
</tr>

and continues to more ... non relevant repetitive data.
4

2 に答える 2

2

基本的にほとんどのHTML解析には、優れたlxmlとそのcssselect機能を使用することをお勧めします。

次に、関心のある各フィールドを次のように選択できます。

from lxml import html
root = html.parse(open('your/file.html')).getroot()

sibling_content = lambda x: [b.getparent().getnext().text_content() for b in
                             root.cssselect("td b:contains('{0}')".format(x))]

fields = ['notificationNodeName', 'packageName', 'notificationEnabled']

for item in zip(*[sibling_content(field) for field in fields]):
    print item
于 2012-08-23T16:23:14.503 に答える
1

また、lxmlをお勧めします。これは、PythonでXMLまたはHTMLを解析するための事実上の標準です。

Davidのアプローチの代替として、xpathsを使用したソリューションを次に示します。

from lxml import html
from lxml import etree


html_file = open('test.html', 'r')
root = html.parse(html_file).getroot()

# Strip those annoying <b> tags for easier xpaths
etree.strip_tags(root,'b')

data_list = root.xpath("//td[text()='notificationDataList']/following-sibling::*")[0]

node_names = data_list.xpath("//td[text()='notificationNodeName']/following-sibling::*/text()")
package_names = data_list.xpath("//td[text()='packageName']/following-sibling::*/text()")
enableds = data_list.xpath("//td[text()='notificationEnabled']/following-sibling::*/text()")

print zip(node_names, package_names, enableds)

出力:

[('package:Notif', 'Package', 'unsched'),
 ('Package_2:notif', 'package_2', 'yes')]
于 2012-08-23T16:42:10.573 に答える