0

ページをスクレイピングし、テーブルからデータを取得しています。目的の最終製品はリストのリストです。

import urllib2
from bs4 import BeautifulSoup

html = BeautifulSoup(urllib2.urlopen('http://domain.com').read(), 'lxml')
tagged_data = [row('td') for row in html('table',{'id' : 'targeted_table'})[0]('tr') ]

# One of the <td>'s has an a tag in it that I need to grab the link from, hence the conditional
clean_data = [[(item.string if item.string is not None else ([item('a')[0].string, item('a')[0]['href']])) for item in info ] for info in tagged_data ]

上記のコードは、次の構造を生成します。

[[[u'data 01',
 'http://domain1.com'],
u'data 02',
u'data 03',
u'data 04'],
[[u'data 11',
 'http://domain2.com'],
u'data 12',
u'data 13',
u'data 14'],
[[u'data 01',
 'http://domain1.com'],
u'data 22',
u'data 23',
u'data 24']]

しかし、私が本当に欲しいのは:

[[u'data 01',
u'http://domain1.com',
u'data 02',
u'data 03',
u'data 04'],
[u'data 11',
u'http://domain2.com',
u'data 12',
u'data 13',
u'data 14'],
[u'data 01',
u'http://domain1.com',
u'data 22',
u'data 23',
u'data 24']]

私も試しました:

clean_data = [[(item.string if item.string is not None else (item('a')[0].string, item('a')[0]['href'])) for item in info ] for info in tagged_data ]

しかし、サブリストの最初の項目にタプル(と思います)を入れます。

[(u'data01',
'http://domain1.com'),
u'data02',
u'data03',
u'data04']

提案は?

サンプルデータ

<table id='targeted_table'>
    <tr>
        <td><a href="http://domain.com">data 01</a></td>
        <td>data 02</td>
        <td>data 03</td>
        <td>data 04</td>
    </tr>
    <tr>
        <td><a href="http://domain.com">data 11</a></td>
        <td>data 12</td>
        <td>data 13</td>
        <td>data 14</td>
    </tr>
    <tr>
        <td><a href="http://domain.com">data 01</a></td>
        <td>data 22</td>
        <td>data 23</td>
        <td>data 24</td>
    </tr>
    <tr>
        <td><a href="http://domain.com">data 01</a></td>
        <td>data 32</td>
        <td>data 33</td>
        <td>data 34</td>
    </tr>
</table>
4

2 に答える 2

2

この線

html = BeautifulSoup(urllib2.urlopen('http://domain.com').read(), 'lxml')

lxml がインストールされていることを意味するため、XPath を使用|してテキストまたは属性値を引き出すことができます。

import urllib2
import lxml.html as LH

html = LH.parse(urllib2.urlopen('http://domain.com'))

clean_data = [[elt for elt in tr.xpath('td/a/text() | td/a/@href | td/text()')]
              for tr in html.xpath('//table[@id="targeted_table"]/tr')]
print(clean_data)

収量

[['http://domain.com', 'data 01', 'data 02', 'data 03', 'data 04'], 
 ['http://domain.com', 'data 11', 'data 12', 'data 13', 'data 14'], 
 ['http://domain.com', 'data 01', 'data 22', 'data 23', 'data 24'],
 ['http://domain.com', 'data 01', 'data 32', 'data 33', 'data 34']]

xpathメソッドへの単一の呼び出しでそれを行うこともできます。

pieces = iter(html.xpath('''//table[@id="targeted_table"]/tr/td/a/text()
                            | //table[@id="targeted_table"]/tr/td/a/@href
                            | //table[@id="targeted_table"]/tr/td/text()'''))
clean_data = zip(*[pieces]*5)
于 2013-08-01T21:20:23.273 に答える
1

リスト内包表記で2 つの要素を発行する場合もあれば、1 つの要素を発行する場合もあります。

「one if [criteria] else two」コードを内包することで、このようなことができます。

clean_data = [[res for item in info for res in (
                  [item.string] if item.string is not None else
                  ([item('a')[0].string, item('a')[0]['href']])
              )]
              for info in tagged_data]

確かに、この方法はあまりクリーンではないと思います。HTML / XML を解析している場合は、ツールをジョブに使用し、乱雑なツリー トラバーサルを避けることをお勧めします。

于 2013-08-01T21:23:46.293 に答える