2017-02-27 52 views
9

Potrzebuję uzyskać dostęp do DOM dokumentu HTML po wykonaniu javascript na stronie. Mam poniższy kod, który łączy się z adresem URL i pobiera dokument. Problem polega na tym, że nigdy nie dostać DOM po modyfikowany javascriptDostęp do DOM przy użyciu WebBrowser

public class CustomBrowser 
{ 
    public CustomBrowser() 
    { 
     // 
     // TODO: Add constructor logic here 
     // 
    } 

    protected string _url; 
    string html = ""; 
    WebBrowser browser; 

    public string GetWebpage(string url) 
    { 
     _url = url; 
     // WebBrowser is an ActiveX control that must be run in a 
     // single-threaded apartment so create a thread to create the 
     // control and generate the thumbnail 
     Thread thread = new Thread(new ThreadStart(GetWebPageWorker)); 
     thread.SetApartmentState(ApartmentState.STA); 
     thread.Start(); 
     thread.Join(); 
     string s = html; 
     return s; 
    } 

    protected void GetWebPageWorker() 
    { 
     browser = new WebBrowser(); 
     // browser.ClientSize = new Size(_width, _height); 
     browser.ScrollBarsEnabled = false; 
     browser.ScriptErrorsSuppressed = true; 
     //browser.DocumentCompleted += browser_DocumentCompleted; 
     browser.Navigate(_url); 

     // Wait for control to load page 
     while (browser.ReadyState != WebBrowserReadyState.Complete) 
      Application.DoEvents(); 

     Thread.Sleep(5000); 


     var documentAsIHtmlDocument3 = (mshtml.IHTMLDocument3)browser.Document.DomDocument; 

     html = documentAsIHtmlDocument3.documentElement.outerHTML; 


     browser.Dispose(); 
    } 


} 

The DOM from google chrome developer tool

The DOM I get in my code

Mam nadzieję, że ktoś może mi pomóc z tym problemem

+0

Proszę nie zamieszczać kodu jako obrazu. Kod pocztowy jako tekst. Powinieneś także używać zdarzeń, aby znaleźć, kiedy nawigacja się zakończy, a nie pętla 'while' z' Application.DoEvents() 'lub' Thread.Sleep() '. –

+0

Dodałem kod jako tekst, obrazy, aby wyjaśnić różnicę między domem w przeglądarce i tym, co otrzymuję –

+0

Co powiesz na użycie alternatywnego sterowania? Na przykład. http://stackoverflow.com/questions/790542/replacing-net-webbrowser-control-w--better-browser-like-chrome – user1946932

Odpowiedz

1

sprawdzić jak strona renderuje w IE7. Przypuszczam, że brakujący znacznik jest dodawany z jQuery, a wersja jQuery 2.2.4 na stronie nie obsługuje IE7. Wydaje mi się, że klasa WebBrowser owija wokół IE7, nawet jeśli masz nowszą wersję IE na swoim komputerze.

Jeśli jesteś właścicielem strony, spróbuj dodać wtyczkę migracji jQuery.

+0

Nie jesteś pewien, czy poniższe informacje byłyby pomocne ?: https://www.cyotek.com/blog/configuring-the-emulation-mode-of-an -internet-explorer-webbrowser-control, https://blogs.msdn.microsoft.com/patricka/2015/01/12/controlling-webbrowser-control-compatibility/, https: //weblog.west-wind.com/posts/2011/may/21/web-browser-control-specifying-the-ie-version i http://stackoverflow.com/questions/17922308/use-latest-version-of-internet-explorer-in- the-webbrowser-control – user1946932

+0

Strona jest poprawnie renderowana w IE7 i zmieniłem jQuery na 1.7.1, ale nic się nie zmieniło. –

+0

Zauważyłem, że nazwy klas div na czarnym zrzucie ekranu powyżej nie znajdują się w podwójnych cudzysłowach, a URL images2.jpg też nie jest, jeśli to oznacza cokolwiek. Czytałem, że XHTML wymaga cytatów. – user1946932

3

Jeśli skrypt po stronie klienta rzeczywiście jest wykonywany w IE7, jak mówisz, problem może być czysto czasowy. Nawet po zakończeniu ładowania dokumentu, nie można dokładnie stwierdzić, kiedy skrypty JS zostaną wykonane. Oczekiwanie na 5 sekund przed próbą dotarcia do documentElement brzmi jak dobry pomysł w teorii; w praktyce element może istnieć wcześniej. Lub, być może, sieć działa wolno, a samo pobieranie skryptu jQuery trwa 5 sekund.

Proponuję przetestować istnienie elementu, którego szukasz (w zależności od przypadku - tagu img). Coś wzdłuż linii

while (browser.Document.GetElementsByTagName("img").Count == 0) { 
    Application.DoEvents(); 
} 

ten sposób nie musiałby linię Thread.Sleep.

+0

Skrypt będzie używany do pobierania obrazów z dowolnego adresu URL, a nie konkretnego, myślę, że to nie zadziała w moim przypadku. –

+0

Jak to możliwe? Nie podoba mi się żaden konkretny adres URL w mojej odpowiedzi. – MrMister

+0

Czego szukam, to pobranie całego dokumentu dom po wykonaniu skryptu ajaxowego lub po stronie klienta. Nie szukam tutaj konkretnego elementu, chcę pobrać wszystkie obrazy na dowolnej stronie HTML, w tym obrazy tła dla każdego tagu, już to zrobiłem, z tym wyjątkiem, że nie mogę pobrać obrazów załadowanych przez zapytanie ajax lub skrypt po stronie klienta. –

2

nie widzę js wykonywane są tutaj, ale mogę sobie wyobrazić, że można znaleźć dokładnie to, czego elementem jest aktualizowany i dołączyć obsługi zdarzeń do kiedy onprpertychange wydarzenie jak rozwiązanie, które jest podane tutaj: C# WebBrowser control -- Get Document Elements After AJAX?

Jeśli js jest przerzucanie elementu przez klasę zamiast idei, następnie można wypożyczyć logikę stąd: How to select a class by GetElementByClass and click on it programmically