Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > .NET Frameworks (точка нет фреймворки) > C# (си шарп)
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.09.2017, 16:14   #1
Aleksandr H.
2 the Nation Glory
Старожил
 
Аватар для Aleksandr H.
 
Регистрация: 27.05.2014
Сообщений: 3,289
По умолчанию Учусь парсить.

#Selenium
#PhantomJS
#ExcelDataReader
#HtmlAgilityPack

Файл проекта: https://drive.google.com/open?id=0Bw...TZudGxXd21XVFk

Для обучения работы с браузером и парсинга страниц, решено сделать приложение которое будет тянуть кроссы фильтров с >>>сайта<<<

Путь получения результата:
1. Считать список для кроссирования. Excel
2. Получить страницу кросса. PhantomJS
3. Найти список аналогов. PhantomJS || HtmlAgilityPack
4. Вывести в DataGridView. C#

Проблема, как и ожидалось , в п.п.2-3. Не всегда получается получить список аналогов. Хотя на скриншоте, который делаю после открытия страницы, все отображено, но не могу найти нужные данные на странице.
Если с
Код:
FindElements(By.CssSelector(..))
хоть иногда но получаю какие-то результаты, то
Код:
DocumentNode.SelectNodes("//*[@id=\"filtersTable\"]");
вообще ничего.

Может страницу надо другим образом получать?

Помогите, попунктно разобраться что и как делать что-бы получить
желаемое.

Вопросы задавать буду тупые и нубские
Кто умер, но не забыт, тот бессмертен.
Лао-Цзы.
Aleksandr H. вне форума Ответить с цитированием
Старый 08.09.2017, 16:38   #2
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Так во втором посмотрите, что в HTML (или Ctrl+U в браузере).
Может элемент JS генерируется, тогда естественно его не будет там.

Если да, то используйте WebDriverWait.

Я использовал такую обертку для упрощения и удобства:

Код:
using System;
using OpenQA.Selenium;
using OpenQA.Selenium.Support.UI;

namespace MyProject.Helpers
{
    public static class WaitHelper
    {
        public static TResult WaitUntil<TResult>(IWebDriver webDriver, TimeSpan timeout, Func<IWebDriver, TResult> condition, string message = "")
        {
            var wait = new WebDriverWait(webDriver, timeout);
            if (!String.IsNullOrEmpty(message))
                wait.Message = message;

            return wait.Until(condition);
        }

        public static TResult WaitUntil<TResult>(IWebDriver webDriver, int timeoutSec, Func<IWebDriver, TResult> condition, string message = "")
        {
            return WaitUntil(webDriver, TimeSpan.FromSeconds(timeoutSec), condition, message);
        }
    }
}
Код:
            WebDriver.Url = "...........";

            var btnLocator = By.CssSelector(".........");

            WaitHelper.WaitUntil(WebDriver, 30,
                ExpectedConditions.ElementExists(btnLocator),
                "button X not found");

            var btn = WebDriver.FindElement(btnLocator);
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.

Последний раз редактировалось Alex11223; 25.09.2019 в 12:32.
Alex11223 вне форума Ответить с цитированием
Старый 09.09.2017, 15:41   #3
Aleksandr H.
2 the Nation Glory
Старожил
 
Аватар для Aleksandr H.
 
Регистрация: 27.05.2014
Сообщений: 3,289
По умолчанию

Цитата:
Сообщение от Alex11223 Посмотреть сообщение
Так во втором посмотрите, что в HTML (или Ctrl+U в браузере).
Перешел по ссылке из 1го сообщений, нажал CtrlU, ищу filtersTable (в div с таким Id должен быть список).
Нахожу
Код:
<div id="filtersTable">                                    
</div>
Списка нету, хотя визуально есть.

Список является результатом нажатия на кнопку справа от поля ввода "Номер фильтра". На нажатие кнопки висит код
Код:
function onclick(event) {
  replacementFNHandler('query', 'Russia', '/wixeurope/Content/img/ajax-loader.gif')
}
Вывод?
Цитата:
Сообщение от Alex11223 Посмотреть сообщение
... элемент JS генерируется, тогда естественно его не будет там.
Решение?
Кто умер, но не забыт, тот бессмертен.
Лао-Цзы.
Aleksandr H. вне форума Ответить с цитированием
Старый 09.09.2017, 15:48   #4
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Я ж написал решение.

А если без браузера, то смотреть запросы и выполнять их самому.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 09.09.2017, 23:46   #5
Aleksandr H.
2 the Nation Glory
Старожил
 
Аватар для Aleksandr H.
 
Регистрация: 27.05.2014
Сообщений: 3,289
По умолчанию

Ваше решение делает то самое, почти, что и моя строка
Код:
PJS.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(15));
А именно ждет определенное время до обнаружения элемента.
Разницы я не увидел, так как не получил полного списка.
код
Код:
private void btnGrabByCSSSelector_Click(object sender, EventArgs e)
        {

            string filtr = null;
            IWebDriver PJS = new PhantomJSDriver();
            PJS.Manage().Window.Maximize();
            PJS.Manage().Timeouts().ImplicitlyWait(TimeSpan.FromSeconds(15));
            foreach (DataGridViewRow row in dataGridView1.Rows)
            {
                try
                {
                    if (row.Cells[0].Value != null)
                    {
                        filtr = row.Cells[0].Value.ToString();
                        string link = "http://wix.ua/cross-list,1714.html?filter_number=" + filtr +
                                       "&languageName=Ukrainian";
                        PJS.Navigate().GoToUrl(link);

                        //Find & Click <querySearchBtn> button. Caption ">"
                        //hope this will return me correct page in 15 secs
                        IWebElement input = PJS.FindElement(By.Id("querySearchBtn"));
                        input.Click();

                        //Should I load text again to PJS?

                        var btnLocator = By.CssSelector("p.overlay-cross.engine-info-normal.engine-info-normal");

                        WaitHelpers.WaitUntil(PJS, 30,
                            ExpectedConditions.ElementExists(btnLocator),
                            "filtersTable not found");

                        List <IWebElement> linkList =
                            PJS.FindElements(btnLocator).ToList();


                        string date = DateTime.Now.ToString("yyyyMMdd_hhmmss", System.Globalization.CultureInfo.GetCultureInfo("en-US"));
                        string outputFileName = $@"{Environment.CurrentDirectory}\Files\{filtr}({date})";
                        //Visual result's inspection
                        (PJS as PhantomJSDriver).GetScreenshot().SaveAsFile($"{outputFileName}.JPG", ScreenshotImageFormat.Jpeg);
                        //Maybe that would better to work with saved doc...
                        //...in order StaleElementReferenceException doesn't come up?
                        File.WriteAllText($"{outputFileName}.htm", PJS.PageSource);

                    //some actions with GridView

                    Application.DoEvents();
                }
                //"Element is no longer attached to the DOM" handle this error.
                catch (StaleElementReferenceException ex)
                {
                    dataGridView2.Rows.Add(filtr, "", "Відповідь не одержано");
                }
            }

            PJS.Quit();
        }
Цитата:
А если без браузера, то смотреть запросы и выполнять их самому.
Ухопился за эту фразу. Ведь использование PhantomJS это без браузера?

Что делаю что-бы получить таблицу результатов?
Ввести номер и нажать на кнопку ">".
На кнопке висит код
Код:
<button onclick="replacementFNHandler('query', 'Russia','/wixeurope/Content/img/ajax-loader.gif')" type="button" id="querySearchBtn" class="search-crosslist">&gt;</button>
надо найти что за зверь replacementFNHandler
Ниже, по тексту страницы, есть запись
Код:
<script src="/Content/js/ajax/replacementFNHandler.js?v=1" type="text/javascript"></script>
понимаем, что нужный скрипт хранится в /Content/js/ajax/
att.jpg
нахожу код функции
Код:
function replacementFNHandler(sender, languageName,loader) {
    var senderAfter = jQuery("#" + sender);
    if (jQuery(senderAfter).val().length < 2) {
        jQuery("#tableContainer").html('');
        jQuery("#ajaxStatementInfo").html(getTranslation("ajaxSelectThreeChars", languageName)).show();
        return;
    }
	jQuery("#tableContainer").html('');
	jQuery("#filterContainer").html('');
	jQuery("#ajaxStatementInfo").html("<img src=\"" + loader + "\">").show();
    var senderValue = jQuery(senderAfter).val();
    if (senderValue) {
        //var trimmedsenderValue = senderValue.split(' ').join('');
		//trimmedsenderValue = trimmedsenderValue.split('-').join('');
		//trimmedsenderValue = trimmedsenderValue.split('/').join('');
		var trimmedsenderValue = senderValue;
		jQuery.ajax({
		    type: "POST",
		    url: "../../../Ajax/ReplacementFilterList?value=" + trimmedsenderValue + "&languageName=" + languageName,
		    contentType: "application/json; charset=utf-8",
		    dataType: "text",
		    data: "{}",
		    success: function(res) {
		    jQuery('#ajaxStatementInfo').hide();
		    jQuery('#tableContainer').html("");
		    jQuery('#filterContainer').html("");
		      //  console.log(res);
		        jQuery('#tableContainer').html(res);
		        setOnClick();
		    }
		});
    }
}
В результате получу JSON'a?
надо узнать что делается по
Код:
url: "../../../Ajax/ReplacementFilterList?value=" + trimmedsenderValue + "&languageName=" + languageName
?
Но как туда(../../../Ajax/ReplacementFilterList)добраться? Или меня не туда понесло с таким анализом?
Кто умер, но не забыт, тот бессмертен.
Лао-Цзы.
Aleksandr H. вне форума Ответить с цитированием
Старый 09.09.2017, 23:56   #6
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

Ну так раз там пустой блок изначально, то ждать надо не его, а элементы внутри.

А запрос можно просто в Network посмотреть.
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 10.09.2017, 14:04   #7
Aleksandr H.
2 the Nation Glory
Старожил
 
Аватар для Aleksandr H.
 
Регистрация: 27.05.2014
Сообщений: 3,289
По умолчанию

https://youtu.be/-IJp8XQnvMQ
<censor>

Может это в разделе JScript надо спрашивать?
Кто умер, но не забыт, тот бессмертен.
Лао-Цзы.

Последний раз редактировалось Аватар; 10.09.2017 в 14:06.
Aleksandr H. вне форума Ответить с цитированием
Старый 10.09.2017, 16:10   #8
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

А разве не работает?

Код:
using System;
using System.Linq;
using OpenQA.Selenium;
using OpenQA.Selenium.PhantomJS;
using OpenQA.Selenium.Support.UI;

namespace ConsoleApplication31
{
    class Program
    {
        static void Main(string[] args)
        {
            using (IWebDriver webDriver = new PhantomJSDriver())
            {
                webDriver.Manage().Window.Maximize();

                string link = "http://wixeurope.com/cross-list,1714.html?filter_number=7465&languageName=Ukrainian";
                webDriver.Navigate().GoToUrl(link);

                var tableCellLocator = By.CssSelector("p.overlay-cross.engine-info-normal.engine-info-normal");

                WaitHelper.WaitUntil(webDriver, 30,
                    ExpectedConditions.ElementExists(tableCellLocator),
                    "filtersTable not found");

                var cells = webDriver.FindElements(tableCellLocator).ToList();

                foreach (var cell in cells)
                {
                    Console.WriteLine(cell.Text);
                }

                ((PhantomJSDriver) webDriver).GetScreenshot().SaveAsFile("output.jpg", ScreenshotImageFormat.Jpeg);
            }
        }
    }
}
Выводит
Цитата:
13711247465
BMW
46221
13717797465
BMW
49465
87465
CARQUEST
42465
0746555
FAUN
...
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Старый 10.09.2017, 21:47   #9
Aleksandr H.
2 the Nation Glory
Старожил
 
Аватар для Aleksandr H.
 
Регистрация: 27.05.2014
Сообщений: 3,289
По умолчанию

Работает...иногда
https://youtu.be/VGZEh1X8qHg
Кто умер, но не забыт, тот бессмертен.
Лао-Цзы.
Aleksandr H. вне форума Ответить с цитированием
Старый 10.09.2017, 21:55   #10
Alex11223
Старожил
 
Аватар для Alex11223
 
Регистрация: 12.01.2011
Сообщений: 19,500
По умолчанию

А мой код?)
Зачем клик по какой-то кнопке вначале?
Ушел с форума, https://www.programmersforum.rocks, alex.pantec@gmail.com, https://github.com/AlexP11223
ЛС отключены Аларом.
Alex11223 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Пишу парсер (учусь) Красноглаз C# (си шарп) 1 02.03.2012 19:48
Учусь писать на c# welcomeTo Помощь студентам 5 21.11.2010 12:56
учусь на финансиста Andery2010 Свободное общение 12 18.04.2010 05:20
Учусь программить _MaKpoC_ Общие вопросы C/C++ 7 26.05.2009 02:35
учусь программировать на паскале fronzer Паскаль, Turbo Pascal, PascalABC.NET 12 10.09.2007 09:37