Guest Posted April 22, 2018 Report Posted April 22, 2018 (edited) Salut, Am o aplicatie care viziteaza multe pagini de pe OLX si apasa pe butonul de aratat numarul de telefon. Folosesc WebBrowser si totul e bine si frumos, butonul este apasat. Eu dupa ce apas butonul respectiv extrag sursa paginii ca mai apoi cu HTMLAgilityPack sau ceva sa extrag numarul de telefon. Pana acum totul merge bine pentru 1 pagina la un moment dat, dar problema apare cand vreau sa vizitez o lista de pagini pentru a face lucrul respectiv. Cred ca este vina controlului WebBrowser pentru ca se misca foarte incet povestea. Adica ii ia zeci de secunde bune pentru o amarata de pagina sa apese butonul si sa descarce sursa dupa. Sa nu mai spun faptul ca fiind un control ActiveX nu pot sa pasez multithreaded spre el... Aveti idee de altceva care ar putea face click pe acel buton si sa descarc sursa updatata dupa ce s-a executat javascriptul care arata numarul de telefon? Am aici codul cu WebBrowser care face treaba asta: public List<String> Viziteaza(List<String> pagini) { List<String> sursePagini = new List<String>(); WebBrowser wb = new WebBrowser(); wb.ScriptErrorsSuppressed = true; // wb.AllowNavigation = true; foreach (String anunt in pagini) { //WebBrowser wb = new WebBrowser(); //wb.ScriptErrorsSuppressed = true; //wb.AllowNavigation = true; //if (!wb.IsBusy) //{ wb.Navigate(anunt); //} //while (wb.ReadyState == WebBrowserReadyState.Loading) //{ // Application.DoEvents(); //} wb.DocumentCompleted += wb_DocumentCompleted; while (wb.ReadyState != WebBrowserReadyState.Complete) //treaba asta ingreuneaza povestea dar fara ea nu pot sa iau sursa { Application.DoEvents(); } if (wb.ReadyState == WebBrowserReadyState.Complete) { StringBuilder htmlcode = new StringBuilder(); foreach (HtmlElement item in wb.Document.All) { htmlcode.Append(item.InnerHtml); } sursePagini.Add(htmlcode.ToString()); } } return sursePagini; } void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e) { HtmlElementCollection links = (sender as WebBrowser).Document.GetElementsByTagName("div"); foreach (HtmlElement link in links) { if (link.OuterHtml.ToString().Contains("phone")) link.InvokeMember("click"); } } Edited April 22, 2018 by Guest Quote
Active Members dancezar Posted April 22, 2018 Active Members Report Posted April 22, 2018 (edited) Inainte sa dai click pe buton, pastreaza intr-o variabila innerHTML-u butonului, dupa ce dai click pe buton fa un while care verifica daca innerHTML-u e diferit de cel pe care l-ai memorat inainte, daca e diferit dai break. Sau vezi care e request-ul ce iti da numarul de telefon si il construiesti manual. Edited April 22, 2018 by dancezar Quote
Guest Posted April 22, 2018 Report Posted April 22, 2018 (edited) 10 minutes ago, dancezar said: Inainte sa dai click pe buton, pastreaza intr-o variabila innerHTML-u butonului, dupa ce dai click pe buton fa un while care verifica daca innerHTML-u e diferit ce cel pe care l-ai memorat inainte, daca e diferit dai break. Sau vezi care e request-ul ce iti da numarul de telefon si il construiesti manual. Ideea e ca ei au butonul de apasat ca sa vezi numarul intr-un div. Dupa cum observi eu in cod caut prin toate div-urile si daca gasesc unul sa aiba in OuterHtml "phone" (deci ala care trebuie), apas pe acel div. Un div de genul asta arata cam asa la ei: <div class="contact-button link-phone {'path':'phone', 'id':'9EI91', 'id_raw': '142689839'} atClickTracking contact-a" data-rel="phone"> <i data-icon="phone"></i> <strong class="xx-large">07xx xxx xxx</strong> <span class="spoiler"> Arata telefon </span> </div> Cand apesi pe buton, se mai adauga "activated" la "atClickTacking contact-a" prin ceva javascript si iti arata numarul, asa fac ei ca sa vada ca ai apasat. Ar mai fi o problema esentiala cu WebBrowser. Nu pot sa il folosesc multithreaded iar eu vizitez mii de pagini, deci ar dura foarte mult chiar si asa. Din ce am inteles un WebRequest sau WebClient ar fi mult mai bune, dar nu am idee cum sa fac sa apas butonul, din ce am inteles astea doua pe care le-am mentionat nu au suport pentru scripturi. Edited April 22, 2018 by Guest Quote
Active Members dancezar Posted April 22, 2018 Active Members Report Posted April 22, 2018 (edited) 32 minutes ago, aismen said: Ideea e ca ei au butonul de apasat ca sa vezi numarul intr-un div. Dupa cum observi eu in cod caut prin toate div-urile si daca gasesc unul sa aiba in OuterHtml "phone" (deci ala care trebuie), apas pe acel div. Un div de genul asta arata cam asa la ei: <div class="contact-button link-phone {'path':'phone', 'id':'9EI91', 'id_raw': '142689839'} atClickTracking contact-a" data-rel="phone"> <i data-icon="phone"></i> <strong class="xx-large">07xx xxx xxx</strong> <span class="spoiler"> Arata telefon </span> </div> Cand apesi pe buton, se mai adauga "activated" la "atClickTacking contact-a" prin ceva javascript si iti arata numarul, asa fac ei ca sa vada ca ai apasat. Ar mai fi o problema esentiala cu WebBrowser. Nu pot sa il folosesc multithreaded iar eu vizitez mii de pagini, deci ar dura foarte mult chiar si asa. Din ce am inteles un WebRequest sau WebClient ar fi mult mai bune, dar nu am idee cum sa fac sa apas butonul, din ce am inteles astea doua pe care le-am mentionat nu au suport pentru scripturi. Uite faza, in pagina HTML din anunt exista un token: <script>var phoneToken ='...';</script> Asta e folosit in request-ul: https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt=4a124a3ce5aa3a4e734101e05b2d19e4d85447793dcabe3f73f7f6c6ae20481600f57e7acf440bd9f9b79e458d44e1507e33e8b4d47b9af6fad8fb2e1798ac6a Token-ul pe care il agati cu un regex il introduci in URL si in cookie fiindca altfel iti va da numarul gol. Ca si proof of concept, uite ceva schitat in python: import re import requests ID="6u9qo" url='https://www.olx.ro/oferta/realizare-site-web-de-informare-si-profesionale-domeniu-webhosting-ID'+ID+'.html' s=requests.session() first=s.get(url,headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"}) html=first.content token=re.findall("var phoneToken = \'(.*?)\';",html) if len(token)==0: print 'token...' exit() token=token[0] print token s.cookies.set('pt',token) request_nr=s.get('https://www.olx.ro/ajax/misc/contact/phone/'+ID+'/?pt='+token,headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"}) html=request_nr.content print html Ce nu trebuie sa uiti este sa bagi o sesiune. Edited April 22, 2018 by dancezar Quote
jetus Posted April 22, 2018 Report Posted April 22, 2018 Il am in php cu mysql pe categorii cu tot ce trebuie, 100euro daca te intereseaza. Quote
Guest Posted April 22, 2018 Report Posted April 22, 2018 Just now, jetus said: Il am in php cu mysql pe categorii cu tot ce trebuie, 100euro daca te intereseaza. Nu, multumesc, vreau sa scriu aplicatia mea dar am dat peste acel impas. Sper sa reusesc cu ce mi-a recomandat dancezar. Quote
Guest Posted April 22, 2018 Report Posted April 22, 2018 1 hour ago, dancezar said: Uite faza, in pagina HTML din anunt exista un token: <script>var phoneToken ='...';</script> Asta e folosit in request-ul: https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt=4a124a3ce5aa3a4e734101e05b2d19e4d85447793dcabe3f73f7f6c6ae20481600f57e7acf440bd9f9b79e458d44e1507e33e8b4d47b9af6fad8fb2e1798ac6a Token-ul pe care il agati cu un regex il introduci in URL si in cookie fiindca altfel iti va da numarul gol. Ca si proof of concept, uite ceva schitat in python: import re import requests ID="6u9qo" url='https://www.olx.ro/oferta/realizare-site-web-de-informare-si-profesionale-domeniu-webhosting-ID'+ID+'.html' s=requests.session() first=s.get(url,headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"}) html=first.content token=re.findall("var phoneToken = \'(.*?)\';",html) if len(token)==0: print 'token...' exit() token=token[0] print token s.cookies.set('pt',token) request_nr=s.get('https://www.olx.ro/ajax/misc/contact/phone/'+ID+'/?pt='+token,headers={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"}) html=request_nr.content print html Ce nu trebuie sa uiti este sa bagi o sesiune. Uite, am facut cum ai spus tu pe exemplul tau, i-am pasat cookieul care trebuie, insa tot imi intoarce 000000 ca si cum nu i-as fi dat cookie cum trebuie string html = string.Empty; string url = @"https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt=81c0388900c4b9f667d9258ae7148fb8636b69b658609a0cd94198b99a6b9192faa6d9420513d6d2d530117e1d3504e7f95daa9d50069a0222be8145eec05bd9"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AutomaticDecompression = DecompressionMethods.GZip; request.AllowAutoRedirect = true; request.CookieContainer = new CookieContainer(); request.CookieContainer.Add(new Cookie("pt", "81c0388900c4b9f667d9258ae7148fb8636b69b658609a0cd94198b99a6b9192faa6d9420513d6d2d530117e1d3504e7f95daa9d50069a0222be8145eec05bd9") { Domain = "www.olx.ro" }); request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { html = reader.ReadToEnd(); } richTextBox1.Text = html; Quote
Active Members dancezar Posted April 22, 2018 Active Members Report Posted April 22, 2018 4 minutes ago, aismen said: Uite, am facut cum ai spus tu pe exemplul tau, i-am pasat cookieul care trebuie, insa tot imi intoarce 000000 ca si cum nu i-as fi dat cookie cum trebuie string html = string.Empty; string url = @"https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt=81c0388900c4b9f667d9258ae7148fb8636b69b658609a0cd94198b99a6b9192faa6d9420513d6d2d530117e1d3504e7f95daa9d50069a0222be8145eec05bd9"; HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.AutomaticDecompression = DecompressionMethods.GZip; request.AllowAutoRedirect = true; request.CookieContainer = new CookieContainer(); request.CookieContainer.Add(new Cookie("pt", "81c0388900c4b9f667d9258ae7148fb8636b69b658609a0cd94198b99a6b9192faa6d9420513d6d2d530117e1d3504e7f95daa9d50069a0222be8145eec05bd9") { Domain = "www.olx.ro" }); request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) using (Stream stream = response.GetResponseStream()) using (StreamReader reader = new StreamReader(stream)) { html = reader.ReadToEnd(); } richTextBox1.Text = html; Acel token se schimba mereu nu e static, si este legat de o sesiune "PHPSessid". Trebuie sa faci un CookieJar iar toate cookie-urile din primul request sa fie trimise si catre al doilea request. Daca am timp si nu reusesti o sa il scriu si in c#. Quote
Guest Posted April 22, 2018 Report Posted April 22, 2018 24 minutes ago, dancezar said: Acel token se schimba mereu nu e static, si este legat de o sesiune "PHPSessid". Trebuie sa faci un CookieJar iar toate cookie-urile din primul request sa fie trimise si catre al doilea request. Daca am timp si nu reusesti o sa il scriu si in c#. Am reusit. Uite: CookieContainer cookies = new CookieContainer(); HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create("https://www.olx.ro/oferta/realizare-site-web-de-informare-si-profesionale-domeniu-webhosting-ID6u9qo.html"); webRequest.CookieContainer = cookies; webRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"; HttpWebResponse response = (HttpWebResponse)webRequest.GetResponse(); StreamReader responseReader = new StreamReader(response.GetResponseStream()); string sResponseHTML = responseReader.ReadToEnd(); string pattern = @"var phoneToken = \'(.*?)\';"; string token = string.Empty; MatchCollection matches = Regex.Matches(sResponseHTML, pattern); foreach (Match match in matches) { token = match.Groups[1].Value; } Uri target = new Uri("https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt=" + token); HttpWebRequest nrRequest = (HttpWebRequest)WebRequest.Create("https://www.olx.ro/ajax/misc/contact/phone/6u9qo/?pt="+token); nrRequest.CookieContainer = cookies; nrRequest.CookieContainer.Add(new Cookie("pt", token) { Domain = target.Host }); nrRequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0"; HttpWebResponse nrResponse = (HttpWebResponse)nrRequest.GetResponse(); StreamReader nrReader = new StreamReader(nrResponse.GetResponseStream()); string nrResponseHTML = nrReader.ReadToEnd(); richTextBox1.Text = nrResponseHTML; Si intoarce numarul care trebuie. Secretul era ca trebuia sa fiu pe aceeasi sesiune cand extrageam tokenul si cand il bagam in cookie, si asta s-a realizat pastrand cookieurile din sesiunea in care am extras tokenul. Acum da nr care trebuie. Multumesc pentru indrumari. Quote
Guest Posted April 22, 2018 Report Posted April 22, 2018 (edited) @dancezar Scuze de deranj, dar poti sa ma ajuti cu o expresie regex care sa extraga id-ul din URL-urile de genul: https://www.olx.ro/oferta/realizare-site-web-de-informare-si-profesionale-domeniu-webhosting-ID6u9qo.html adica ce e intre ID si .html Edit: Am rezolvat. "ID(.*)\.html$" e patternul. Edited April 22, 2018 by Guest Quote