나는 이미이 질문 1 과 2를 보았지만 나를 위해 일하지는 않는다.
WebDriver에서 잘 작동하는 객체에 대한 Xpath를 만들고 있지만 HtmlAgilityPack을 사용하여 노드를 선택하려고 할 때 어떤 경우에는 작동하지 않습니다.
최신 HtmlAgilityPack 1.4.9를 사용 중입니다.
예를 들어, 다음 은 페이지입니다.
빨간색으로 강조 표시된 개체의 xpath는 다음과 같습니다.
// section [@ id = 'main-content'] / div 2 / div / div / div / div / div / p 1 / a
이와 유사하게 그림
그것은 xpath입니다.
// section [@ id = 'main-content'] / div 2 / div / div / div / div / ul / li 2 / a
이 두 Xpath는 WebDriver에서 절대적으로 정상적으로 작동하지만 HtmlAgility 팩에서 개체를 찾을 수 없습니다.
내가 시도한 첫 번째
HtmlAgilityPack.HtmlNode.ElementsFlags.Remove ( "p")
그것은 일하기 시작했는데 왜 필요한가? 또한 두 번째 행운은 없습니다.
ElementFlags에서 제거해야하는 특정 태그 목록이 있습니까? 어떤 것이 있다면 그 영향은 무엇인가?
내 요구 사항은 WebDriver가 작동하는 것처럼 HtmlAgility 팩에서 Xpath를 사용하여 개체를 가져 오는 것입니다.
어떤 도움이라도 대단히 감사하겠습니다.
편집 1 :
HAP에서 얻는 XPATH는 div / div / div / div / a와 같은 긴 것들입니다. Simon Simon이 제공 한 예제의 VB.Net 코드가 있습니다.
Dim selectedNode As HtmlAgilityPack.HtmlNode = htmlAgilityDoc.DocumentNode.SelectSingleNode("//section[@id='main-content']//div[@class='pane-content']//a")
Dim xpathValue As String = selectedNode.XPath
그렇다면 우리가 얻은 xpathValue는 다음과 같습니다.
/ html 1 / 본문 1 / 섹션 1 / div 2 / div 1 / div 1 / div 1 / div 1 / div 1 / a 1
WebDriver는 XPATH로 작업 할 때 항상 대상 브라우저에 의존합니다. 기술적으로 브라우저에 대한 멋진 다리입니다 (브라우저가 Firefox 또는 Chrome이든 - 최대 11 개의 IE는 XPATH를 지원하지 않습니다)
불행하게도 브라우저 메모리에있는 DOM (엘리먼트와 애트리뷰트 구조)은 아마도 HTML 애자일 팩에 제공 한 DOM 과 같지 않다 . 브라우저 메모리 (예 : document.OuterHtml에 해당)에서 DOM의 내용으로 HAP을로드하면 동일 할 수 있습니다. 일반적으로 개발자는 HAP을 사용하여 브라우저없이 사이트를 스크랩하므로 HTTP GET 요청의 네트워크 스트림이나 원시 파일에서 피드를 제공하기 때문에 이러한 경우는 아닙니다.
이 문제는 쉽게 설명 할 수 있습니다. 예를 들어, 다음을 포함하는 파일을 만드는 경우 :
<table><tr><td>hello world</td></tr></table>
(html, body 태그 없음, 이것은 사실 잘못된 html 파일입니다)
HAP을 사용하면 다음과 같이로드 할 수 있습니다.
HtmlDocument doc = new HtmlDocument();
doc.Load(myFile);
그리고 HAP 구조는 간단히 다음과 같습니다.
+table
+tr
+td
'hello world'
HAP은 브라우저가 아니며 파서이며 HTML 사양을 실제로 알지 못합니다. 여러 태그를 구문 분석하고 DOM을 작성하는 방법을 알고 있습니다. 예를 들어, 문서가 HTML로 시작해야하고, BODY를 포함해야하거나, 브라우저에 의해 추론 될 때 TABLE 요소가 항상 TBODY 하위를 가짐을 알 수 없습니다.
Chrome 브라우저에서이 파일을 열고 검사하여 XPATH에 TD 요소를 요청하면 다음과 같이 표시됩니다.
/html/body/table/tbody/tr/td
Chrome은이 기능을 자체적으로 만들었 기 때문에 두 시스템이 일치하지 않습니다.
소스 HTML에서 사용할 수있는 id
속성이있는 경우 스토리가 더 유용합니다 (예 : 다음 HTML 사용).
<table><tr><td id='hw'>hello world</td></tr></table>
Chrome은 다음 XPATH를보고합니다 (가능한 한 id
속성을 사용하려고 시도합니다).
//*[@id="hw"]
또한 HAP에서도 사용할 수 있습니다. 그러나 이것은 항상 작동하지 않습니다. 예를 들어, 다음 HTML
<table id='hw'><tr><td>hello world</td></tr></table>
이제 Chrome에서이 XPATH를 TD에 생성합니다.
//*[@id="mytable"]/tbody/tr/td
보시다시피, 이것은 추측 된 TBODY 때문에 HAP에서 다시 사용할 수 없습니다.
결국, XPath를 생성 한 브라우저를 맹목적으로 사용하는 것만으로는 다른 환경에서 XPATH를 생성 할 수 없습니다. 다른 맥락에서, 당신은 다른 discriminants을 찾아야 할 것입니다.
사실 XPath가 변경에 더 저항력을 갖기 때문에 나는 개인적으로 그것이 좋은 방법이라고 생각합니다. 그러나 당신은 생각해야합니다 :-)
이제 다시 사례로 돌아 가자. :)
다음 C # 샘플 콘솔 사례가 제대로 작동해야합니다.
static void Main(string[] args)
{
var web = new HtmlWeb();
var doc = web.Load("http://www2.epa.gov/languages/traditional-chinese");
var node = doc.DocumentNode.SelectSingleNode("//section[@id='main-content']//div[@class='pane-content']//a");
Console.WriteLine(node.OuterHtml); // displays <a href="http://www.oehha.ca.gov/fish/pdf/59329_CHINESE.pdf">...etc...</a>"
}
스트림이나 파일의 구조를 보거나 (또는 브라우저가 표시하는 내용조차도주의를 기울이고 TBODY를 피하십시오 ...) 가장 쉬운 방법은
id
찾으십시오 (브라우저와 마찬가지로) 그리고 / 또는 p/p/p/div/a/div/whatever
좋든 p/p/p/div/a/div/whatever
여기에서 main-content
id
속성 다음에 특수 클래스가있는 DIV를 (재귀 적으로 //
) 살펴보고 사용 가능한 첫 번째 하위 A
를 다시 (재귀 적으로) 봅니다.
이 XPATH는 webdriver와 HAP에서 작동해야합니다.
이 XPATH도 작동합니다 : //div[@class='pane-content']//a
그러나 조금 느슨해 보입니다. id
속성에 기초를 두는 것이 좋습니다.