2016-07-06 3 views
1

Xpath를 처음 사용했습니다. Xpath를 사용하여 파이썬에서 일부 데이터를 구문 분석하려고합니다.다른 형제까지 형제 자매를 따라 Xpath

다음 HTML 구문 분석 :

<table> 
    <tr> 
     <td class="DT">29-04-14</td> 
     <td class="Regio">Text</td> 
     <td class="Md">Text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="SomeClass">Some other text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="SomeOtherClass">Some more text</td> 
    </tr> 
    <tr> 
     <td class="DT">22-04-14</td> 
     <td class="Regio">Text</td> 
     <td class="Md">Text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="OmsAm">more text</td> 
    </tr> 
    <tr> 
     <td class="DT">30-04-14</td> 
     <td class="Regio">Text</td> 
     <td class="Md">Text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="OmsBr">Some other Text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="OmsBr">More Text</td> 
    </tr> 
    <tr> 
     <td></td> 
     <td></td> 
     <td class="OmsBr">Some different text</td> 
    </tr> 
</table> 

을 나는까지 형제 자매에게 모든 <td>의 일부 값을 다음 <tr>을 자신의 <td>의 몇 가지 값으로 <tr><tr>하지만 다음의 모든 <td>이 필요합니다.

예. 내 현재 위치를 처음 <tr>됩니다 가정, 나는이 테이블 셀 필요 : 만 필요 4

<tr> 
    <td class="DT">22-04-14</td> 
    <td class="Regio">Text</td> 
    <td class="Md">Text</td> 
</tr> 

테이블 행 내 현재 위치를 가정 할

<td class="SomeClass">Some other text</td> 
    <td class="SomeOtherClass">Some more text</td> 

<td class="OmsAm">more text</td> 

이것은 모든 형제 자매를 얻으려는 Xpath입니다. 그러나 그것은 나를 얻습니다. 모두 follinwg 형제 자매 여러분, 아닙니다. 그것은 멈추어야하는 형제를 제외하고 : ./following-sibling::tr/td[1][not(text()[1])]/..

나는 Kayesian 방법을 구현해야한다고 생각하지만, 내 경우에는 이것을 이해하지 못한다. 어떤 도움이라도 정말 감탄할 것입니다!

+0

내가 심각하게 나는 그의 의 몇 가지 값으로 후 형제에게 다음의 모든 필요하지만,'하지 않는 모든 몇 가지 값으로 다음 까지 s.' – SomeDude

+0

파이썬 코드를 보여주십시오. 이 문제를 해결하는 XPath 식은 오래 동안 지속될 것입니다. 오히려 비교적 간단한 XPath 표현식을 작성한 다음 결과를 파이썬으로 처리해야합니다. –

+0

'를 경계로''을 분류하고 싶습니까? –

답변

0

내가 질문을 잘못 해석 될 수 있지만, 각 <tr><td class="DT">xx-xx-xx</td>을 위해, 당신은 그것을 후 모든 <tr>을 원하고, 다음 <tr><td class="DT">xx-xx-xx</td>하기 전에, 하나 개의 패턴과 형제 행 다음이 "경계"<tr><td class="DT">xx-xx-xx</td> 요소 및 선택에 루프 경우 전에 얼마나 많은 "경계선"이 발견되었는지에 대한 조건.

설명해 보려면 lxml을 사용하십시오. 첫째, 우리는 샘플 입력에서 문서를 만들 :

>>> import lxml.html 
>>> t = '''<table> 
...  <tr> 
...   <td class="DT">29-04-14</td> 
...   <td class="Regio">Text</td> 
...   <td class="Md">Text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="SomeClass">Some other text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="SomeOtherClass">Some more text</td> 
...  </tr> 
...  <tr> 
...   <td class="DT">22-04-14</td> 
...   <td class="Regio">Text</td> 
...   <td class="Md">Text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="OmsAm">more text</td> 
...  </tr> 
...  <tr> 
...   <td class="DT">30-04-14</td> 
...   <td class="Regio">Text</td> 
...   <td class="Md">Text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="OmsBr">Some other Text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="OmsBr">More Text</td> 
...  </tr> 
...  <tr> 
...   <td></td> 
...   <td></td> 
...   <td class="OmsBr">Some different text</td> 
...  </tr> 
... </table>''' 
>>> doc = lxml.html.fromstring(t) 

을 이제, 이러한 <tr><td class="DT">xx-xx-xx</td> 계산하자 (우리

>>> doc.xpath('//table/tr[td/@class="DT"]') 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab005e8>, <Element tr at 0x7f948ab00638>] 
>>> doc.xpath('count(//table/tr[td/@class="DT"])') 
3.0 
>>> list(enumerate(doc.xpath('//table/tr[td/@class="DT"]'), start=1)) 
[(1, <Element tr at 0x7f948ab00548>), (2, <Element tr at 0x7f948ab005e8>), (3, <Element tr at 0x7f948ab00638>)] 

우리는 이러한 행에 루프와 문서에 후 오는 행을 선택할 수 있습니다 '이것들이있는 행 "을 참조하십시오"텍스트 노드를 선택 것이다 :

>>> for cnt, row in enumerate(doc.xpath('//table/tr[td/@class="DT"]'), start=1): 
...  print(row.xpath('./following-sibling::tr/td/text()')) 
... 
['Some other text', 'Some more text', '22-04-14', 'Text', 'Text', 'more text', '30-04-14', 'Text', 'Text', 'Some other Text', 'More Text', 'Some different text'] 
['more text', '30-04-14', 'Text', 'Text', 'Some other Text', 'More Text', 'Some different text'] 
['Some other Text', 'More Text', 'Some different text'] 

우리는이 끝날 때까지, 각 반복의 모든 행을 너무 많은 행을 선택하고. 다음 행에 대해 추가 "종료"조건이 필요합니다.

우리는 루프에서 tr[td/@class="DT"]를 계산하고, 각각의 행이 tr[td/@class="DT"] 앞에 얼마나 많은 우리가 확인할 수 : 2에 대한

row.xpath('./following-sibling::tr[count(./preceding-sibling::tr[td/@class="DT"])=1] 

:

row.xpath('./following-sibling::tr[count(./preceding-sibling::tr[td/@class="DT"])=2] 
1 세트의

>>> for cnt, row in enumerate(doc.xpath('//table/tr[td/@class="DT"]'), start=1): 
...  print(row.xpath('./following-sibling::tr[count(./preceding-sibling::tr[td/@class="DT"])=$count]', count=cnt)) 
... 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab005e8>, <Element tr at 0x7f948ec02f98>] 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab00638>] 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab005e8>, <Element tr at 0x7f948ab00688>] 
>>> 

흠, 우리는 각각의 반복에 너무 1 개 행을 선택하고 :

따라서, 루프에, 우리는 LXML (an underrated XPath feature supported by lxml)과는 XPath 변수의 현재 카운트를 이용할 수있다. <tr><td class="DT">30-04-14</td>도 1 우리는 반복 당 결과의 수를 잘 보이는 <td class="DT">

>>> for cnt, row in enumerate(doc.xpath('//table/tr[td/@class="DT"]'), start=1): 
...  print(row.xpath(''' 
...   ./following-sibling::tr[count(./preceding-sibling::tr[td/@class="DT"])=$count] 
...        [not(td/@class="DT")]''', count=cnt)) 
... 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab005e8>] 
[<Element tr at 0x7f948ab00548>] 
[<Element tr at 0x7f948ab00548>, <Element tr at 0x7f948ab005e8>, <Element tr at 0x7f948ab00688>] 
>>> 

이없는 행을 선택하기위한 추가 조건을 추가 할 수 있습니다

<tr><td class="DT"> 앞에 있기 때문에

있다고. 의 마지막 텍스트 노드를 사용하여 확인하자

>>> for cnt, row in enumerate(doc.xpath('//table/tr[td/@class="DT"]'), start=1): 
...  print(row.xpath(''' 
...   ./following-sibling::tr[count(./preceding-sibling::tr[td/@class="DT"])=$count] 
...        [not(td/@class="DT")] 
...    /td/text()''', count=cnt)) 
... 
['Some other text', 'Some more text'] 
['more text'] 
['Some other Text', 'More Text', 'Some different text'] 
>>> 
+0

와우, 훌륭한 설명과 완벽하게 작동합니다! 고마워요! – Gino

관련 문제