Модераторы: Partizan, gambit

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Подскажите как правильно, Строки 
:(
    Опции темы
ilya_cska
Дата 20.3.2008, 14:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Скачиваю HTML и перевожу в String. Сам он довольно здоровый (~50кб). Подскажите как будет привильнее всего сделать (я в принцепе сделал, но больно плохо), чтоб вытащить с HTML определенные данные. Ниже я привел кусок HTML , как вы поняли мне нужно вытащить баланс, фамилию и т.д.

Код

 <td class="index_block_content_wide"><img src="/images/box_purple.gif">&nbsp;<b>Здравствуйте, Фамилия И.О</b>
        <br><br><img src="/images/arrow.gif">&nbsp;&nbsp;<b>Ваш баланс равен <span OnMouseMove="move_tip(tip4,event.clientX,event.clientY)" OnMouseOut="hide_tip(tip4)" style='font-size:30px;color:#af2525;'><u><nobr>-81.7</nobr></u></span> рублей.</b><span class="tip" id="tip4">Ваш актуальный баланс на данный момент.<br>Обновляется каждые 15 минут.</span><br><br><img src="/images/arrow.gif">&nbsp;&nbsp;<b>Кредит равен <span OnMouseMove="move_tip(tip5,event.clientX,event.clientY)" OnMouseOut="hide_tip(tip5)"><u>100</u></span> рублей.</b>

PM MAIL   Вверх
Freak_FB
Дата 20.3.2008, 14:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Ктулхувед
**


Профиль
Группа: Участник
Сообщений: 296
Регистрация: 13.10.2006

Репутация: 1
Всего: 4



Я бы использовал регулярные выражения.

Код

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;

namespace Fam
{
    class Program
    {
        static void Main(string[] args)
        {
            string str = "<td class=\"index_block_content_wide\"><img src=\"/images/box_purple.gif\">&nbsp;<b>Здравствуйте, Фамилия И.О</b><br><br><img src=\"/images/arrow.gif\">&nbsp;&nbsp;<b>Ваш баланс равен <span OnMouseMove=\"move_tip(tip4,event.clientX,event.clientY)\" OnMouseOut=\"hide_tip(tip4)\" style='font-size:30px;color:#af2525;'><u><nobr>-81.7</nobr></u></span> рублей.</b><span class=\"tip\" id=\"tip4\">Ваш актуальный баланс на данный момент.<br>Обновляется каждые 15 минут.</span><br><br><img src=\"/images/arrow.gif\">&nbsp;&nbsp;<b>Кредит равен <span OnMouseMove=\"move_tip(tip5,event.clientX,event.clientY)\" OnMouseOut=\"hide_tip(tip5)\"><u>100</u></span> рублей.</b>";

            string pattern = "Здравствуйте, (?<name>.*)</b>(.*)Ваш баланс равен (.*)<u><nobr>(?<balance>.*)</nobr></u>(.*)Кредит равен(.*)<u>(?<kredit>.*)</u>";
            
            Regex re = new Regex(pattern);
            Match m = re.Match(str);

            Console.WriteLine(m.Groups["name"].Value);
            Console.WriteLine(m.Groups["balance"].Value);
            Console.WriteLine(m.Groups["kredit"].Value);
        }
    }
}



--------------------
user posted image
user posted image
Тонет Ктулху, все медведы горят в огне.
Я Креведко, очень страшно сегодня мне.

PM MAIL ICQ Skype GTalk Jabber   Вверх
ilya_cska
Дата 22.3.2008, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Freak_FB так как ты написал, скорее всего не получится, потому что я получаю строку во время выполнения программы. И весь HTML занимает 1500 строчек.



Это сообщение отредактировал(а) ilya_cska - 22.3.2008, 10:40
PM MAIL   Вверх
marcusmae
Дата 22.3.2008, 11:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



ilya_cska, а почему не получится? = Единственно, HTML-код нужно получить в переменную str в любой момент выполнения программы, ессесно, до того, как прорабатывают регулярные выражения. Или сделать функцию :

Код

        static void GetUserInfo(string str, out string name, out string balance, out string credit)
        {
            string pattern = "Здравствуйте, (?<name>.*)</b>(.*)Ваш баланс равен (.*)<u><nobr>(?<balance>.*)</nobr></u>(.*)Кредит равен(.*)<u>(?<kredit>.*)</u>";
            
            Regex re = new Regex(pattern);
            Match m = re.Match(str);

            name = m.Groups["name"].Value;
            balance = m.Groups["balance"].Value;
            credit = m.Groups["kredit"].Value;
        }


Строчка HTML-кода, подаваемого функции должна лишь содержать тег <td>, либо же в одну строчку можно положить ВЕСЬ код (50кб - не так уж и много), но тогда выходные параметры имя-баланс-кредит должны стать массивами ( и из групп match-а значения доставать в массивы ).

Это сообщение отредактировал(а) marcusmae - 22.3.2008, 11:58


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
ilya_cska
Дата 22.3.2008, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Тут происходит как бы наложение строки на строку?
PM MAIL   Вверх
marcusmae
Дата 22.3.2008, 14:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Цитата(ilya_cska @  22.3.2008,  13:36 Найти цитируемый пост)
Тут происходит как бы наложение строки на строку?


где? = в аргументе с out? = несовсем. Это - "аргумент на выход", который должен объявить вызывающий, а инициализировать вызываемый. Есть ещё ref - "аргумент по ссылке", который должен объявить и инициализировать вызывающий, а вызываемый _может_ его изменить, причём если изменит, то вызывающий об этом узнает. Подробнее - в MSDN.

Если не то имели ввиду, то дайте сюда какой-нибудь полный текст HTML (из тех, с кот. Вы работаете) - может тогда удастся показать нагляднее.


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
ilya_cska
Дата 22.3.2008, 14:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Если не то имели ввиду, то дайте сюда какой-нибудь полный текст HTML (из тех, с кот. Вы работаете) - может тогда удастся показать нагляднее.

Вот, ссылка на HTML. click
Если открыть файл с помощью Notpad++ то информация, которую мне нужно вытащить, находится с 1275 строчке.

PM MAIL   Вверх
marcusmae
Дата 23.3.2008, 21:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



ilya_cska, в классе User описана необходимая функциональность, связанная с пользователем. Помимо полей-только-для-чтения Name, Balance и Credit, есть конструктор, вывод сводной информации Summary и статическая функция для извлечения информации из текста HTML :

Код

        /// <summary>
        /// Try to get the user info from the specified string text.
        /// </summary>
        /// <param name="text">The string text.</param>
        /// <param name="user">The user instance.</param>
        /// <returns>
        /// The value indicating if the user info presents in the specified text.
        /// </returns>
        public static bool TryGetUser(string text, out User user)
        {
            string pattern =
                "Здравствуйте,(?<name>.*)</b>(.*)Ваш баланс равен(.*)<u><nobr>(?<balance>.*)</nobr></u>(.*)<b>Кредит равен(.*)<u>(?<credit>.*)</u></span> рублей.</b><span class=\"tip\" id=\"tip5\">";

            user = null;

            Match match = new Regex(pattern).Match(text);

            if ((match.Groups["name"].Success) &&
                (match.Groups["balance"].Success) &&
                (match.Groups["credit"].Success))
            {
                decimal balance, credit;
                if (Decimal.TryParse(match.Groups["balance"].Value, out balance) &&
                    Decimal.TryParse(match.Groups["credit"].Value, out credit))
                {
                    user = new User(match.Groups["name"].Value.Trim(), balance, credit);
                    return true;
                }
            }

            return false;
        }


Оригинальный паттерн регулярного выражения Freak_FB пришлось слегка подредактировать для того, чтобы кредит по признакам не путался со следующими за ним записями. Рекомендую тщательно перепроверить его переносимость, протестировав на большом множестве реальных страниц.

Рубли из строки переводятся в численное выражение, что может быть излишне, если не нужно с ними делать никакой арифметики.

Вызов мог бы выглядеть так :

Код

        static void Main(string[] args)
        {
            string filename = "qwer.txt";

            // Read from file to string variable.
            string htmlText;
            using (StreamReader streamReader = new StreamReader(filename,
                Encoding.GetEncoding("windows-1251")))
            {
                htmlText = streamReader.ReadToEnd().Replace(Environment.NewLine, "");
            }

            // Search with specified pattern.
            User user;
            if (User.TryGetUser(htmlText, out user))
            {
                Console.WriteLine("Информация о пользователе :");
                Console.WriteLine(user.Summary);
            }
            else
            {
                Console.WriteLine("В указанном файле информации о пользователе не найдено.");
            }
            Console.ReadKey();
        }
    }


Открыли файл читателем и слили весь текст в одну строку. Далее обращаю внимание на крайне нежелательную (например, в плане скорострельности) операцию удаления из текста символов перевода каретки :

Код

.Replace(Environment.NewLine, "");


Компьютеры, конечно, железные, но могли бы - вздохнули бы горько smile Если её не делать, то паттерн в нынешнем виде не будет работать, то есть, нужно либо очень аккуратно его модифицировать, либо сразу иметь текст без многострочности.

Полный код программы присоединён.


Это сообщение отредактировал(а) marcusmae - 23.3.2008, 21:09

Присоединённый файл ( Кол-во скачиваний: 2 )
Присоединённый файл  Program.cs 3,74 Kb


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
ilya_cska
Дата 24.3.2008, 08:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



marcusmae, мож глупый вопрос, а ты файл qwer.txt не исправлял? А то я код твой скачал, а программа выполняет условие
Код

Console.WriteLine("В указанном файле информации о пользователе не найдено.");

PM MAIL   Вверх
marcusmae
Дата 24.3.2008, 13:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



ilya_cska, нет, я ничего не исправлял. Изменим метод загрузки так, чтобы файл получался напрямую из урл (собсна, так сразу нужно было сделать) :

Код

        static void Main(string[] args)
        {
            string uriString = "http://artem-bazar.110mb.com/qwer.txt";

            // Read from file to string variable.
            string htmlText;
            using (StreamReader streamReader = new StreamReader(
                new WebClient().OpenRead(uriString), Encoding.GetEncoding("windows-1251")))
            {
                htmlText = streamReader.ReadToEnd().Replace(Environment.NewLine, "");
            }

            // Search with specified pattern.
            User user;
            if (User.TryGetUser(htmlText, out user))
            {
                Console.WriteLine("Информация о пользователе :");
                Console.WriteLine(user.Summary);
            }
            else
            {
                Console.WriteLine("В указанном файле информации о пользователе не найдено.");
            }
            Console.ReadKey();
        }


Результат :

Код

Информация о пользователе :
Имя : Фамилия !
Баланс : -11.55 рублей
Кредит : 100 рублей


Это сообщение отредактировал(а) marcusmae - 24.3.2008, 13:30


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
ilya_cska
Дата 24.3.2008, 14:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



marcusmae скинь пожалуйста весь код, а то компилятор ругается.
PM MAIL   Вверх
ilya_cska
Дата 24.3.2008, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Все сделал, только все равно пишет В указанном файле информации о пользователе не найдено
полный код
Код

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Net;

namespace HTMLRegex
{
    class Program
    {
       /* static void Main(string[] args)
        {
            string filename = "qwer.txt";

            // Read from file to string variable.
            string htmlText;
            using (StreamReader streamReader = new StreamReader(filename,
                Encoding.GetEncoding("windows-1251")))
            {
                htmlText = streamReader.ReadToEnd().Replace(Environment.NewLine, "");
            }

            // Search with specified pattern.
            User user;
            if (User.TryGetUser(htmlText, out user))
            {
                Console.WriteLine("Информация о пользователе :");
                Console.WriteLine(user.Summary);
            }
            else
            {
                Console.WriteLine("В указанном файле информации о пользователе не найдено.");
            }
            Console.ReadKey();
        }*/

        static void Main(string[] args)
        {
            string uriString = "http://artem-bazar.110mb.com/qwer.txt";
            
            // Read from file to string variable.
            string htmlText;

            WebClient myWebClient = new WebClient();
            using (StreamReader streamReader = new StreamReader(
                myWebClient.OpenRead(uriString), Encoding.GetEncoding("windows-1251")))
            {
                htmlText = streamReader.ReadToEnd().Replace(Environment.NewLine, "");
            }

            // Search with specified pattern.
            User user;
            if (User.TryGetUser(htmlText, out user))
            {
                Console.WriteLine("Информация о пользователе :");
                Console.WriteLine(user.Summary);
            }
            else
            {
                Console.WriteLine("В указанном файле информации о пользователе не найдено.");
            }
            Console.ReadKey();
        }
    }

    /// <summary>
    /// Defines the user class.
    /// </summary>
    class User
    {
        /// <summary>
        /// Try to get the user info from the specified string text.
        /// </summary>
        /// <param name="text">The string text.</param>
        /// <param name="user">The user instance.</param>
        /// <returns>
        /// The value indicating if the user info presents in the specified text.
        /// </returns>
        public static bool TryGetUser(string text, out User user)
        {
            string pattern ="Здравствуйте,(?<name>.*)</b>(.*)Ваш баланс равен(.*)<u><nobr>(?<balance>.*)</nobr></u>(.*)<b>Кредит равен(.*)<u>(?<credit>.*)</u></span> рублей.</b><span class=\"tip\" id=\"tip5\">";

            user = null;

            Match match = new Regex(pattern).Match(text);

            if ((match.Groups["name"].Success) &&
                (match.Groups["balance"].Success) &&
                (match.Groups["credit"].Success))
            {
                decimal balance, credit;
                if (Decimal.TryParse(match.Groups["balance"].Value, out balance) &&
                    Decimal.TryParse(match.Groups["credit"].Value, out credit))
                {
                    user = new User(match.Groups["name"].Value.Trim(), balance, credit);
                    return true;
                }
            }

            return false;
        }

        string name;
        /// <summary>
        /// Get the user name.
        /// </summary>
        public string Name { get { return this.name; } }

        decimal balance;
        /// <summary>
        /// Get the user balance.
        /// </summary>
        public decimal Balance { get { return this.balance; } }

        decimal credit;
        /// <summary>
        /// Get the user credit.
        /// </summary>
        public decimal Credit { get { return this.credit; } }

        /// <summary>
        /// Initialize a new instance of the user class.
        /// </summary>
        /// <param name="name">The user name.</param>
        /// <param name="balance">The user balance.</param>
        /// <param name="credit">The user credit.</param>
        public User(string name, decimal balance, decimal credit)
        {
            this.name = name;
            this.balance = balance; this.credit = credit;
        }

        public string Summary
        {
            get
            {
                return
                    "Имя : " + this.Name + Environment.NewLine +
                    "Баланс : " + this.Balance + " рублей" + Environment.NewLine +
                    "Кредит : " + this.credit + " рублей" + Environment.NewLine;
            }
        }
    }
}




Это сообщение отредактировал(а) ilya_cska - 24.3.2008, 14:53
PM MAIL   Вверх
marcusmae
Дата 24.3.2008, 16:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


stravaganza
**


Профиль
Группа: Участник
Сообщений: 874
Регистрация: 26.3.2006

Репутация: 22
Всего: 39



Уф, ну это мистификация smile Мне лично достаточно того, что она работает, и я Вас не обманываю :

user posted image

Посмотрите, какие у Вас могут возникнуть проблемы. На строковую переменную с текстом через отладчик, например, проверьте, что там всё в порядке с кириллицей и вообще с кодировкой. Успешно перенёс программку на другой компьютер, правда Program.cs пришлось пересохранить в UTF-8... Да вообще, за полдня-то уж можно было всю программу вдоль и поперёк отладчиком излазить - было бы на то Ваше желание. smile А ещё лучше, если бы кто-нибудь ещё сделал независимое тестирование smile 

Это сообщение отредактировал(а) marcusmae - 24.3.2008, 16:51


--------------------
ἀπὸ μηχανῆς θεός
PM MAIL ICQ GTalk   Вверх
ivashkanet
Дата 24.3.2008, 17:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Кодю потиху
****


Профиль
Группа: Участник Клуба
Сообщений: 3684
Регистрация: 23.2.2006
Где: Гомель, Беларусь

Репутация: 47
Всего: 149



Может кому понадобиться:  HTML to XHTML Conversion with SGMLReader.
PM MAIL WWW ICQ   Вверх
ilya_cska
Дата 25.3.2008, 11:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 165
Регистрация: 25.1.2008

Репутация: нет
Всего: нет



Все, спасибо marcusmae.  smile Не знаю в чем была проблема, не стал разбираться,  я на основе Вашего кода сделел свою функцию. Просто до этого не было времени.  smile 
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0607 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.