2017-02-12 90 views
-1

欣賞Python Xpath的幫助。我有以下的XML代碼。 目前,我正在使用python並逐行閱讀,然後試圖提取它。但是我意識到這些表格是1000行,並且逐行閱讀並將邏輯放在它之上遠遠超過了我。使用Python Xpath將數據提取到csv文件

我想從XML代碼,並輸入該數據提取到一個CSV文件中。

如何使用Xpath來做到這一點?

示例XML代碼:

<thead> 
    <tr> 
     <th class="section" data-bind="text: name">Ratios</th> 
     <!-- ko foreach : $parent.dataPoints --> 
      <th> 
       <span data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod">FY2013</span> 
       <br> 
       <span data-bind="text: periodDate, format: 'date'">30/Jun/2013</span> 
      </th> 

      <th> 
       <span data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod">FY2014</span> 
       <br> 
       <span data-bind="text: periodDate, format: 'date'">30/Jun/2014</span> 
      </th> 

      <th> 
       <span data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod">FY2015</span> 
       <br> 
       <span data-bind="text: periodDate, format: 'date'">30/Jun/2015</span> 
      </th> 

      <th> 
       <span data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod">FY2016</span> 
       <br> 
       <span data-bind="text: periodDate, format: 'date'">30/Jun/2016</span> 
      </th> 

      <th> 
       <span data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod">LTM Ending</span> 
       <br> 
       <span data-bind="text: periodDate, format: 'date'">31/Dec/2016</span> 
      </th> 
     <!-- /ko --> 
     <th class="uncheck" data-bind="visible: $root.series().length > 0" style="display: none;">&nbsp;</th> 
    </tr> 
</thead> 
<tbody> 
    <!-- ko foreach : dataPoints --> 
     <tr data-bind="css: { 'odd': ($index() % 2 == 0) }" class="odd"> 
      <td class="checkbox left"> 
       <div class="trigger" data-bind="attr: { 'data-name': property, 'data-group': group }, click: function(data, event) { $root.handleClick($root, data, event); }" data-name="returnAssets" data-group="ratio"> 
        <span class="name" data-bind="text: name">Return on Assets</span> 
        <span data-bind="visible: $data.hasOwnProperty('glossaryTerm')"> 
         <img src="img/info.png" alt="" data-bind="tooltip: $data.hasOwnProperty('glossaryTerm') ? glossaryTerm : null" tooltip-copy="Return on Assets is a measure of company profitability relative to total assets. It is calculated by dividing tax-effective EBIT (Earnings before Interest and Tax) by Average Total Assets over a 12-months period." class="tooltip-item"> 
        </span> 
       </div> 
       <input type="checkbox"> 
      </td> 
      <!-- ko foreach : $root.dataPoints --> 
       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="14.6931" data-name="returnAssets">14.693</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="13.5242" data-name="returnAssets">13.524</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="14.5923" data-name="returnAssets">14.592</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="13.0935" data-name="returnAssets">13.094</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="15.4657" data-name="returnAssets">15.466</td> 
      <!-- /ko --> 
      <td class="uncheck" data-bind="visible: $root.series().length > 0, click: function(data, event) { $root.handleClick($root, data, event); }" style="display: none;"> 
       <span data-bind="visible: $root.canUncheck($root, property)" style="display: none;">[UNCHART]</span> 
      </td> 
     </tr> 

     <tr data-bind="css: { 'odd': ($index() % 2 == 0) }"> 
      <td class="checkbox left"> 
       <div class="trigger" data-bind="attr: { 'data-name': property, 'data-group': group }, click: function(data, event) { $root.handleClick($root, data, event); }" data-name="returnCapital" data-group="ratio"> 
        <span class="name" data-bind="text: name">Return on Capital</span> 
        <span data-bind="visible: $data.hasOwnProperty('glossaryTerm')"> 
         <img src="img/info.png" alt="" data-bind="tooltip: $data.hasOwnProperty('glossaryTerm') ? glossaryTerm : null" tooltip-copy="Return on Capital is a measure of company profitability relative to total capitals. It is calculated by dividing tax-effective EBIT (Earnings before Interest and Tax) by Average Total Capital over a 12-months period." class="tooltip-item"> 
        </span> 
       </div> 
       <input type="checkbox"> 
      </td> 
      <!-- ko foreach : $root.dataPoints --> 
       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="30.0726" data-name="returnCapital">30.073</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="25.6597" data-name="returnCapital">25.66</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="26.4617" data-name="returnCapital">26.462</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="26.0215" data-name="returnCapital">26.021</td> 

       <td data-bind="text: $data.hasOwnProperty($parent.property) &amp;&amp; $data[$parent.property] != null? $data[$parent.property] : '-', formatNonZeroValue: 'number', attr: { 'data-value': $data.hasOwnProperty($parent.property) ? $data[$parent.property] : null, 'data-name': $parent.property }" data-value="27.67" data-name="returnCapital">27.67</td> 
      <!-- /ko --> 
      <td class="uncheck" data-bind="visible: $root.series().length > 0, click: function(data, event) { $root.handleClick($root, data, event); }" style="display: none;"> 
       <span data-bind="visible: $root.canUncheck($root, property)" style="display: none;">[UNCHART]</span> 
      </td> 
     </tr> 
</tbody> 

樣本輸出到Excel作爲一個表報表

enter image description here

+0

不幸的是,這不是XML,但HTML後者是比前者的標記規則剛性不足和解析爲XML失敗。例如'
'標籤應該是自我關閉的'
',它是格式良好的XML,甚至可以打破XPath調用。 – Parfait

+0

我應該使用哪些其他方法來獲取所需的輸出表? –

回答

0

是的,它是可能的lxml.etree解析HTML。但確切的代碼取決於文件中使用的命名空間。 假設你在你的文件的開頭有

<!DOCTYPE html> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
</head> 
<body> 

,此代碼的工作:

from lxml import etree 

parser = etree.XMLParser(attribute_defaults=False, load_dtd=True, resolve_entities=True,remove_comments=False, ns_clean=True, recover=True) 
file = "C:\\test1.html" # your filename here 
data = etree.parse(file, parser=parser) 
headers = etree.XPath('''//h:span [@data-bind="text: absPeriod.indexOf('LTM') != -1 ? 'LTM Ending' : absPeriod"] ''', namespaces={'h':"http://www.w3.org/1999/xhtml"}) 
dates = etree.XPath('''//h:span [@data-bind="text: periodDate, format: 'date'"] ''', namespaces={'h':"http://www.w3.org/1999/xhtml"}) 
assets = etree.XPath('''//h:td [@data-name="returnAssets"]''', namespaces={'h':"http://www.w3.org/1999/xhtml"}) 
capitals = etree.XPath('''//h:td [@data-name="returnCapital"]''', namespaces={'h':"http://www.w3.org/1999/xhtml"}) 
header = [x.text for x in headers(data)] 
date = [x.text for x in dates(data)] 
asset = [x.text for x in assets(data)] 
capital = [x.text for x in capitals(data)] 
print(header) 
print(date) 
print(asset) 
print(capital) 

爲您提供:

['FY2013', 'FY2014', 'FY2015', 'FY2016', 'LTM Ending'] 
['30/Jun/2013', '30/Jun/2014', '30/Jun/2015', '30/Jun/2016', '31/Dec/2016'] 
['14.693', '13.524', '14.592', '13.094', '15.466'] 
['30.073', '25.66', '26.462', '26.021', '27.67'] 

這個開始,你現在可以把數據一個CSV(對不起,我不這樣做)。

1

我已經解決了之前這個問題,並寫了一個HTML解析器https://pypi.python.org/pypi/messytables去表編程訪問。

您應該使用lxml.html爲HTML,不lxml.etree。界面非常相似。

從本質上講,你應該循環每個table元素提取行(tr),每個tr提取tdth,並得到他們每個人的文字。我不會誇大你試圖獲得的元素。

如果碰到一個問題,與當時不得不重組你出來的數據,你會發現https://github.com/sensiblecodeio/xypath有用。 [免責聲明:我寫這個最]

相關問題