XPath는 브라우저 및 HtmlAgilityPack에서 다른 결과를 제공합니다.

c# html-agility-pack xpath

문제

C # 프로그램에서 HtmlAgilityPack을 사용하여 웹 페이지의 섹션을 구문 분석하려고합니다. 아래는 페이지의이 섹션을 간략하게 나타낸 것입니다 (2011 년 1 월 30 일 오후 2시 40 분 수정).

<html>
    <body>
        <div id="main-box">
            <div>
                <div>...</div>
                <div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <a href="/some/other/path">
                                    <img src="/path/to/img" />
                                </a>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=123">Correct</a> extra text
                            </p>
                        </div>
                        <div>
                            ...
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=456&b=123">Never Selected</a>
                                            and <a href="/test/path?a=789">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                No "a" tag this time
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    <li>
                                        <span>
                                            <span style="display:none;">
                                                <a href="/some/other/path">Never Selected</a>
                                            </span>
                                        </span>
                                    </li>
                                    <li>
                                        <span>
                                            <a href="/test/path?a=abc&b=123">Correct</a>
                                            and <a href="/test/path?a=def">Wrongly Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <span>
                                    <a href="/test/path?a=ghi">Correct</a>
                                </span>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=jkl">Wrongly Selected</a> extra text
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=mno&b=123">Never Selected</a>
                                            and <a href="/test/path?a=pqr">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                </div>
            </div>
        </div>
    </body>
</html>

나는 첫 번째 "GET"매개 변수 "a"클래스 "row-box"(각 단어의 "correct"라는 단어가있는 단어)를 가진 각 div의 3 번째 또는 4 번째 자식 div에있는 첫 번째 " 위의 예에서). 이 노드를 얻는 다음 XPath와 Chrome의 관리자 및 Firefox 용 Firepath 애드온 (읽기 쉽도록 줄 바꿈 됨)에서 이러한 노드 만 생성했습니다.

<html>
    <body>
        <div id="main-box">
            <div>
                <div>...</div>
                <div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <a href="/some/other/path">
                                    <img src="/path/to/img" />
                                </a>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=123">Correct</a> extra text
                            </p>
                        </div>
                        <div>
                            ...
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=456&b=123">Never Selected</a>
                                            and <a href="/test/path?a=789">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                No "a" tag this time
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    <li>
                                        <span>
                                            <span style="display:none;">
                                                <a href="/some/other/path">Never Selected</a>
                                            </span>
                                        </span>
                                    </li>
                                    <li>
                                        <span>
                                            <a href="/test/path?a=abc&b=123">Correct</a>
                                            and <a href="/test/path?a=def">Wrongly Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <span>
                                    <a href="/test/path?a=ghi">Correct</a>
                                </span>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=jkl">Wrongly Selected</a> extra text
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=mno&b=123">Never Selected</a>
                                            and <a href="/test/path?a=pqr">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                </div>
            </div>
        </div>
    </body>
</html>

그러나 HttpWebRequest를 사용하여이 페이지를로드하고 응답 스트림을 HtmlDocument 객체에로드하고이 XPath를 사용하여 DocumentNode 속성에서 SelectNodes (xpath)를 호출하면 올바른 노드 세 개뿐만 아니라 텍스트가있는 두 개의 태그도 반환됩니다. 위의 예에서 "잘못 선택"되었습니다. 위의 XPath를 사용하는 것과 같은 효과가있는 것으로 나타났습니다. 마지막 "[1]"이 없으면 다음과 같습니다 (읽기 쉽도록 줄 바꿈 됨).

<html>
    <body>
        <div id="main-box">
            <div>
                <div>...</div>
                <div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <a href="/some/other/path">
                                    <img src="/path/to/img" />
                                </a>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=123">Correct</a> extra text
                            </p>
                        </div>
                        <div>
                            ...
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=456&b=123">Never Selected</a>
                                            and <a href="/test/path?a=789">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                No "a" tag this time
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    <li>
                                        <span>
                                            <span style="display:none;">
                                                <a href="/some/other/path">Never Selected</a>
                                            </span>
                                        </span>
                                    </li>
                                    <li>
                                        <span>
                                            <a href="/test/path?a=abc&b=123">Correct</a>
                                            and <a href="/test/path?a=def">Wrongly Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <span>
                                    <a href="/test/path?a=ghi">Correct</a>
                                </span>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=jkl">Wrongly Selected</a> extra text
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=mno&b=123">Never Selected</a>
                                            and <a href="/test/path?a=pqr">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                </div>
            </div>
        </div>
    </body>
</html>

나는 최신 버전의 HtmlAgilityPack을 사용하고 있는지, XPath에 몇 가지 변형을 시도하여 임의의 최대 길이 또는 다른 간단한 문제가 발생했는지를 확인하고 성공하지 못한 비슷한 문제를 연구하려고 노력했다. 동일한 기본 개념을 사용하여 더 간단한 HTML 구조를 테스트 해 보았습니다.하지만이 문제를 재현 할 수 없었으므로 HtmlAgilityPack이이 구조에서 구문을 분석하는 방법에 미묘한 문제가있을 수 있습니다.

누구든지이 문제를 일으킬 수있는 것을 알고 있거나 올바른 노드를 얻고 잘하면 HtmlAgilityPack에서 문제를 일으키지 않는 XPath 표현식을 작성하는 더 좋은 방법이 있다면 크게 감사 할 것입니다.

편집하다

제안 된대로, 여기에 내가 사용하고있는 C # 코드의 단순화 된 버전이 나와 있습니다.이 코드는 문제를 재현합니다.

<html>
    <body>
        <div id="main-box">
            <div>
                <div>...</div>
                <div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <a href="/some/other/path">
                                    <img src="/path/to/img" />
                                </a>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=123">Correct</a> extra text
                            </p>
                        </div>
                        <div>
                            ...
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=456&b=123">Never Selected</a>
                                            and <a href="/test/path?a=789">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                No "a" tag this time
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    <li>
                                        <span>
                                            <span style="display:none;">
                                                <a href="/some/other/path">Never Selected</a>
                                            </span>
                                        </span>
                                    </li>
                                    <li>
                                        <span>
                                            <a href="/test/path?a=abc&b=123">Correct</a>
                                            and <a href="/test/path?a=def">Wrongly Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                    <div class="other-classes row-box">
                        <div>...</div>
                        <div>...</div>
                        <div>
                            <p>
                                <span>
                                    <a href="/test/path?a=ghi">Correct</a>
                                </span>
                            </p>
                            <p>
                                ...
                                <a href="/test/path?a=jkl">Wrongly Selected</a> extra text
                            </p>
                        </div>
                        <div>
                            <p>
                                <ul>
                                    ...
                                    <li>
                                        <span>
                                            <a href="/test/path?a=mno&b=123">Never Selected</a>
                                            and <a href="/test/path?a=pqr">Never Selected</a>.
                                        </span>
                                    </li>
                                </ul>
                            </p>
                        </div>
                        ...
                    </div>

                </div>
            </div>
        </div>
    </body>
</html>

인기 답변

업데이트 된 HTML을 기반으로하는 새로운 대답

//a[contains(@href,'a=')][1] 필터는 직접 부모로부터 첫 번째 <a> 요소를 선택하기 때문에 사용할 수 없습니다.

필터에 하위 연산자를 포함하려면 대괄호를 추가해야합니다. 예 :

(//a[contains(@href,'a=')])[1]

그러나 다른 노드 집합의 각 노드에 첫 번째 자손 필터를 적용하도록 확장하면 결과 xpath 표현식이 유효하지 않습니다.

(//a[contains(@href,'a=')])[1]

우리는 두 단계로 나누어야한다고 생각합니다.

  1. 우리가 원하는 특정 링크가 포함 된 div 요소 그룹을 가져옵니다.
  2. 해당 그룹의 각 요소에서 첫 번째 자손 링크 요소를 가져옵니다.

C #에서는 다음과 같이 보입니다.

(//a[contains(@href,'a=')])[1]

이전 답변

페이지 를 가이드로 사용하여 xpath 표현식을 작성했습니다.

HtmlAgilityPack에서 실행할 때 다음 세 요소 만 반환됩니다.

(//a[contains(@href,'a=')])[1]

다음은 표현식의 분류입니다.

(//a[contains(@href,'a=')])[1]

귀하의 질문에 xpath의 주요 차이점은 /descendant::a[contains(@href,'a=') and position()=1] vs /descendant::a[contains(@href,'a=')][1] . [1] 별도로 적용하는 것은 첫 번째 자손 대신 첫 번째 자식으로 필터링합니다.




아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.
아래 라이선스: CC-BY-SA with attribution
와 제휴하지 않음 Stack Overflow
이 KB는 합법적입니까? 예, 이유를 알아보십시오.