2011-03-05 5 views
2

반복되는 질문 인 경우 사과하지만 SO 또는 내가 필요한 것을 처리하는 것으로 보이는 다른 질문을 찾을 수 없습니다. 여기 내 질문입니다 :XPath : 현재 노드 속성을 사용하여 현재 노드와 다음 노드의 텍스트를 선택하십시오.

this 웹 페이지의 정보를 얻으려면 scrapy을 사용하고 있습니다.

<p class="titlestyle">ANT101H5 Introduction to Biological Anthropology and Archaeology 
         <span class='distribution'>(SCI)</span></p> 

<span class='normaltext'> 
Anthropology is the global and holistic study of human biology and behaviour, and includes four subfields: biological anthropology, archaeology, sociocultural anthropology and linguistics. The material covered is directed to answering the question: What makes us human? This course is a survey of biological anthropology and archaeology. [<span class='Helpcourse' 
      onMouseover="showtip(this,event,'24 Lectures')" 
      onMouseout="hidetip()">24L</span>, <span class='Helpcourse' 
      onMouseover="showtip(this,event,'12 Tutorials')" 
      onMouseout="hidetip()">12T</span>]<br> 

<span class='title2'>Exclusion: </span><a href='javascript:OpenCourse("WEBCOURSENOTFOUND.html")'>ANT100Y5</a><br> 

<span class='title2'>Prerequisite: </span><a href='javascript:OpenCourse("WEBCOURSEANT102H5.pl?fv=1")'>ANT102H5</a><br> 
</span><br/><br/<br/> 

거의 모든 페이지에 위의 코드 블록과 같습니다 명확하게하기 위해, 다음은 나에게 관심있는 해당 웹 페이지의 소스 코드의 블록입니다.

    생물 인류학 및 고고학에
  1. ANT101H5 소개
  2. 제외 대상 : ANT100Y5
  3. 전제 조건 :이 모든에서

    , 내가 잡아 필요 ANT102H5

문제는이다 Exclusion:을 그 <span class="title2"> 안에 있고 ANT100Y5은 다음 안에 들어 있습니다. <a>.

이 소스 코드에서 두 가지를 모두 포착 할 수없는 것 같습니다. 그것은 "당신이 다른 SO 질문을보고하지 않는 장님 경우에도,

hxs = HtmlXPathSelector(response) 
    sites = hxs.select("//*[(name() = 'p' and @class = 'titlestyle') or (name() = 'a' and @href and preceding-sibling::'//span/@class=title2')]") 

내가이 어떤 도움을 주셔서 감사합니다 것 : 현재, 나는 보이는 ANT100Y5을 잡기 위해 시도 (그리고 실패) 코드를 이 답변에 완벽하게 "(이 경우 자신이 투표를 닫을 것입니다). 나는 정말 많이 끝내 준다. 사전에

감사

편집 :

class regcalSpider(BaseSpider): 
    name = "disc" 
    allowed_domains = ['www.utm.utoronto.ca'] 
    start_urls = ['http://www.utm.utoronto.ca/regcal/WEBLISTCOURSES1.html'] 

    def parse(self, response): 
      items = [] 
      hxs = HtmlXPathSelector(response) 
      sites = hxs.select("/*/p/text()[1] | \ 
           (//span[@class='title2'])[1]/text() | \ 
           (//span[@class='title2'])[1]/following-sibling::a[1]/text() | \ 
           (//span[@class='title2'])[2]/text() | \ 
           (//span[@class='title2'])[2]/following-sibling::a[1]/text()") 

      for site in sites: 
        item = RegcalItem() 
        item['title'] = site.select("a/text()").extract() 
        item['link'] = site.select("a/@href").extract() 
        item['desc'] = site.select("text()").extract() 
        items.append(item) 
      return items 

      filename = response.url.split("/")[-2] 
      open(filename, 'wb').write(response.body) 

나에게이 결과를 제공합니다 :

나는 다음과 같은 코드를 사용하고 @Dimitre 제안 변경 후 전체 원본 코드

[{"title": [], "link": [], "desc": []}, 
{"title": [], "link": [], "desc": []}, 
{"title": [], "link": [], "desc": []}] 

Th 제가 필요한 결과물이 아닙니까? 내가 도대체 ​​뭘 잘못하고있는 겁니까? 앞서 언급 한대로이 스크립트는 this에 있습니다.

답변

1

내 대답 매우 @Flack들처럼 :

수많은 마감이 XML 문서 (수정 제공된 하나를 갖는 공개되지 않은,243,753,210의 단일 상위 요소의 모든 포장에) :

<body> 
    <p class="titlestyle">ANT101H5 Introduction to Biological Anthropology and Archaeology 
     <span class='distribution'>(SCI)</span> 
    </p> 
    <span class='normaltext'> Anthropology is the global and holistic study of human biology and behaviour, and includes four subfields: biological anthropology, archaeology, sociocultural anthropology and linguistics. The material covered is directed to answering the question: What makes us human? This course is a survey of biological anthropology and archaeology. [ 
     <span class='Helpcourse' onMouseover="showtip(this,event,'24 Lectures')" onMouseout="hidetip()">24L</span>, 
     <span class='Helpcourse' onMouseover="showtip(this,event,'12 Tutorials')" onMouseout="hidetip()">12T</span>] 
     <br/> 
     <span class='title2'>Exclusion: </span> 
     <a href='javascript:OpenCourse("WEBCOURSENOTFOUND.html")'>ANT100Y5</a> 
     <br/> 
     <span class='title2'>Prerequisite: </span> 
     <a href='javascript:OpenCourse("WEBCOURSEANT102H5.pl?fv=1")'>ANT102H5</a> 
     <br/> 
    </span> 
    <br/> 
    <br/> 
    <br/> 
</body> 

이 XPath 식 : 평가

normalize-space(/*/p/text()[1]) 

가 원하는 문자열을 생성합니다 (주변 시세는 결과에 있지 않습니다.

"ANT101H5 Introduction to Biological Anthropology and Archaeology" 

이 XPath 식 : 평가 한 다음 원하는 결과를 생성

concat((//span[@class='title2'])[1], 
      (//span[@class='title2'])[1] 
        /following-sibling::a[1] 
      ) 

: 나는 생산 정확한 문자열)을 보여주기 위해 추가

"Exclusion: ANT100Y5" 

이 XPath 식 :

이 특별한 경우에는 약어 //이 필요하지 않습니다 그것은 리드하기 때문에 사실이 약자는 항상 가능하면 피해야한다 :

"Prerequisite: ANT102H5" 

: 평가

concat((//span[@class='title2'])[2], 
      (//span[@class='title2'])[2] 
        /following-sibling::a[1] 
      ) 

는 다음 원하는 결과를 생성 많은 경우 전체 (하위) 트리 순회를 일으키는 표현식 평가가 느립니다. 제공된 XML 조각이 XML 문서의 전체 구조를 제공하지 않기 때문에 의도적으로 '//'를 사용하고 있습니다.또한,이 제대로 지수는 //를 사용의 결과가 (주변 괄호주의)하는 방법을 보여줍니다 -

가 UPDATE 그렇게 노력에 매우 자주 실수를 방지하는 데 도움이 : 영업 이익은 단일 XPath 식을 요구 한 그 필요한 모든 텍스트 노드를 선택 - 여기있다 : 위와 같은 XML 문서에 적용 할 때

/*/p/text()[1] 
    | 
    (//span[@class='title2'])[1]/text() 
    | 
    (//span[@class='title2'])[1]/following-sibling::a[1]/text() 
    | 
    (//span[@class='title2'])[2]/text() 
    | 
    (//span[@class='title2'])[2]/following-sibling::a[1]/text() 

는 텍스트 노드의 연결은 정확하게 필요한 것입니다 :

ANT101H5 Introduction to Biological Anthropology and Archaeology   
     Exclusion: ANT100Y5Prerequisite: ANT102H5 
이 변환은 (이 응답 이전에 지정된) 같은 XML 문서에 적용

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 
<xsl:output omit-xml-declaration="yes" indent="yes"/> 
<xsl:strip-space elements="*"/> 

<xsl:template match="/"> 
    <xsl:copy-of select= 
    "/*/p/text()[1] 
    | 
    (//span[@class='title2'])[1]/text() 
    | 
    (//span[@class='title2'])[1]/following-sibling::a[1]/text() 
    | 
    (//span[@class='title2'])[2]/text() 
    | 
    (//span[@class='title2'])[2]/following-sibling::a[1]/text() 
    "/> 
</xsl:template> 
</xsl:stylesheet> 

, 원하는 정확한 결과가 생성된다 :

이 결과는 다음 XSLT 변환을 실행하여 확인할 수있다 : 마지막으로

ANT101H5 Introduction to Biological Anthropology and Archaeology   
     Exclusion: ANT100Y5Prerequisite: ANT102H5 

: 다음 단일 XPath 표현은로 정리 후 (정확하게 모든 제공된 링크, HTML 페이지에서 텍스트 노드를 원 선택 잘 구성된 XML 형식) :

(//p[@class='titlestyle'])[2]/text()[1] 
| 
    (//span[@class='title2'])[2]/text() 
| 
    (//span[@class='title2'])[2]/following-sibling::a[1]/text() 
| 
    (//span[@class='title2'])[3]/text() 
| 
    (//span[@class='title2'])[3]/following-sibling::a[1]/text() 
+0

나는 어떻게 이러한 것들을 개별적으로 얻을 수 있겠지만 어떻게 3 가지를 모두 얻을 수있는 하나의 xpath select 문을 쓸 수 있을까? 이런 기본적인 질문을하는 것에 대해 유감 스럽지만, 이것은 xpath에 대한 첫 번째 진출입니다. – inspectorG4dget

+1

@ inspectorG4dget : Simpy는 모든 문자열을 단일 문자열로 연결하기 위해'concat()'함수를 사용합니다 :'concat (ExprA, ExprB, ExprC)' –

+0

@ Dimitre : 그러나 ExprA, ExprB 및 ExprC가 모두 하나의 문자열로 연결되는 경우 xpath는 어떻게 구별됩니까? – inspectorG4dget

3

.1. ANT101H5 Introduction to Biological Anthropology and Archaeology

p[@class='titlestyle']/text() 

.2. Exclusion: ANT100Y5

concat(
    span/span[@class='title2'][1], 
    span/span[@class='title2'][1]/following-sibling::a[1] 
    ) 

.3. Prerequisite: ANT102H5

concat(
    span/span[@class='title2'][2], 
    span/span[@class='title2'][2]/following-sibling::a[1] 
    ) 
+0

+1 정답은 –

+0

+1 정답입니다. Dimitre의 답변을 받아 들일 것입니다. 추가 설명이 필요한 경우에만 필요하고 감사합니다. 내가 두 가지 대답을 받아 들일 수 있다면, 나는 이것도 받아 들일 것이다. – inspectorG4dget

2

참조하는 세 개의 노드를 선택하는 것은 어렵지 않습니다 (Flack과 같은 기술 사용). 어려운 점은 (a) 원하지 않는 다른 것들을 선택하지 않고 선택하는 것, (b) 입력이 약간 다를 때 여전히 선택하기에 충분히 견고한 선택을하는 것입니다. 입력 내용을 정확히 알지 못한다고 가정해야합니다. 그렇게했다면 XPath 표현식을 작성할 필요가 없습니다.

우리는 당신이 원하는 세 가지를 말했습니다. 그러나이 세 가지를 선택하고 다른 것을 선택하지 않는 기준은 무엇입니까? 당신이 찾고있는 것에 대해 얼마나 알고 있습니까?

XPath 문제로 문제를 표현했지만 다르게 다룰 것입니다. XSLT를 사용하여 더 나은 구조로 표시 한 입력을 변환하여 시작할 것입니다. 특히, <p> 요소 내에없는 모든 형제 요소를 <p> 요소로 래핑하고, <br>으로 끝나는 연속 요소의 각 그룹을 단락으로 처리하려고합니다. XSLT 2.0에서 <xsl:for-each-group group-ending-with> 구문을 사용하면 너무 어려움없이이 작업을 수행 할 수 있습니다.

+0

그런 식으로 할 수 있어요. 그러나 나는 정말로 그렇지 않다. 또한 웹 페이지가 내가 본 방식대로 정확하게 구성되어 있다는 것을 알고 있습니다. 내가 알고있는 다른 모든 파싱 기술보다 간단하기 때문에 xpath를 사용하고 싶다. 당신이 내가 다른 것을 사용해야한다고 생각한다면, 나는 그것을 배우기에 반대하지 않습니다. 이 프로젝트를 잠시 동안 진행해 왔으며 이것이 마지막 작품이며 훨씬 더 연장하기를 원하지 않습니다. – inspectorG4dget

관련 문제