Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.59/22: Рейтинг темы: голосов - 22, средняя оценка - 4.59
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
1
.NET 4.x

Парсинг странички, выбор нужного текста и сохранение в файл csv

06.08.2012, 14:38. Показов 4123. Ответов 12
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
программа парсинга.
Парсит странички,выберая нужный текст и сохраняет в файл csv.
Сделал:
1 перебирает все странички с нужной инфой по ссылкам на след страницы.
2заходит по ссылкам в описание нужного объекта для вытаскивания инфы.
3парсит нужную инфу
4 Сохранение - тут ошибка.Программа запускается ,работает,вроде бы как проходит все этапы но в файл пустой.Помогите найти ошибку.
код класса:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.Net;
using System.IO;
 
namespace Console_Parser
{ 
    class Parser
    {
        string url = "http://www.057.ua/dosug/446";
        // Свойство класса 
       public string URL 
        { 
            set { url = value;}
            get { return url;}
        }
        public static string LoadWebPage(string url)// метод загрузки всех страниц
        {
            try
            {
                WebRequest reqGET = System.Net.WebRequest.Create(url);
                System.Net.WebResponse resp = reqGET.GetResponse();
                Stream stream = resp.GetResponseStream();
                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding(65001));
                string s = sr.ReadToEnd();
                return s;
            }
            catch
            {
                return string.Empty;
            }
        }
       public void ParseLink(string url)
        {
            string s = LoadWebPage(url);
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(s);
            HtmlNodeCollection C = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//td[@valign='top']/h2/a");
            if (C != null)
            {
                foreach(HtmlNode n in C)
                {
                    if (n.Attributes["href"] != null)
                    {
                        string u = s + n.Attributes["href"].Value;
                        string cafe_opisanie = LoadWebPage(u);
                        HtmlAgilityPack.HtmlDocument d = new HtmlDocument();
                        d.LoadHtml(cafe_opisanie);
                       // HtmlNodeCollection Reyt = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//p[@class='small_3']/strong");
                        HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//tbody//td[@valign='top']//h2");
                       // HtmlNodeCollection streetsandphone = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//td[@valign='top']/strong");
                        List<string> Cafe = new List<string>();
                        if (Names != null)
                        {
                            for (int y = 0; y < Names.Count; y++) // заполняет все три коллекции
                            {
 
                                //Cafe.Add(Reyt[y].InnerText);
                                 Cafe.Add(Names[y].InnerText);
                                //Cafe.Add(streetsandphone[y].InnerText);
                            }
                            
                        }
                        Save(Cafe); 
                    }
 
                }
               
            }
            
        }
       public static void Save(List<string> Cafe)
        {
            string[] txtmas = new string[Cafe.Count];
            for (int y = 0; y < Cafe.Count; y++)
            {
                txtmas[y] = string.Format(Cafe[y]);
            }
            StreamWriter SW = File.AppendText(@"bla bla bla 1.csv"); 
            //SW.Flush();
           // SW.WriteLine("#File_adres_names_phones");
            for (int y = 0; y < txtmas.Length; y++)
            {
                SW.WriteLine(txtmas[y]);
            }
            SW.Close();
        }
 
      public IEnumerable<string> GetUrls(string url ="") 
        {
            if (url == "") // точка остановы (отладка)
            {
                url = this.url;
            }
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                doc.LoadHtml(LoadWebPage(url));// загружаем страницу из параметра url
                foreach (HtmlNode link in doc.GetElementbyId("paginationControl").ChildNodes)/
                {
                    if (link.Name == "a")// если содержит атрибут "a"
                    {
                        yield return link.GetAttributeValue("href", string.Empty);
                    }
                }
          
            
        }
 
    }
}
Код выполнения:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
 
namespace Console_Parser
{
    class Program
    {
 
        static void Main(string[] args)
        {
            
            Console.WriteLine("Begin work");
            Parser WorkParser = new Parser();
            Console.WriteLine("Connect to url");
            WorkParser.ParseLink(@"http://www.057.ua/dosug/446/");
            Console.WriteLine("Begin Parse");
            foreach (string link in WorkParser.GetUrls(@"http://www.057.ua/dosug/446"))
            {
                WorkParser.ParseLink(string.Concat(@"http://www.057.ua", link));
            }
            Console.WriteLine("Parse done");
            Console.WriteLine("Saving to file");
            Console.WriteLine("WorkDone");
            Console.WriteLine("To Exit Please enter -q-");
            Console.ReadKey();
        }
    }
}
ошибка я так подозреваю где то в методе public void ParseLink(string url) но какая именно не знаю.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
06.08.2012, 14:38
Ответы с готовыми решениями:

Парсинг и сохранение csv файла
есть вот такая реализация сохранения в фаил csv но я бы хотел узнать как можно реализовать такую...

Парсинг XML и выбор нужного узла
как выбрать определенный узел из xml? при вызове XmlNode.SelectSingleNode(&quot;title&quot;).InnerText...

Выбор нужного текста в html
Добрый день. Такой вопрос возник. Решил составить базу по одному сайту. Достал html код. Нужные...

Сохранение из формы в CSV файл
Имеется форма &lt;form action=&quot;registration.php&quot; method=&quot;post&quot; name=&quot;registration&quot;&gt; &lt;input...

12
canopen
06.08.2012, 16:48
  #2

Не по теме:

А вы умеете отладчиком пользоваться? Если нет, то это удобный случай научиться. Всегда пригодится.

0
200 / 168 / 38
Регистрация: 21.10.2011
Сообщений: 178
06.08.2012, 17:26 3
Проблема в строке
C#
1
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//tbody//td[@valign='top']//h2");
Нужен другой xpath.
Например,
C#
1
2
3
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//table//tr//td[@valign='top']//h2");
//или
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//*//td[@valign='top']//h2");
Вроде оба выдают что-то осмысленное, но не проверял
1
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
07.08.2012, 13:02  [ТС] 4
спасибо попробую.
Отладчиком не умею,тоже попробую.Спасибо.

Добавлено через 14 минут
попробовал,подставил по очереди
C#
1
2
3
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//table//tr//td[@valign='top']//h2");
//или
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//*//td[@valign='top']//h2");
зависает
на
C#
1
2
3
4
5
Console.WriteLine("Begin Parse");
            foreach (string link in WorkParser.GetUrls(@"http://www.057.ua/dosug/446"))
            {
                WorkParser.ParseLink(string.Concat(@"http://www.057.ua", link));
            }
в консольке пишет Begin Parse и дальше дело не идёт

Добавлено через 29 минут
оно сохраняет в файле но только одну страничку и добовляет инфу с первой странички много раз пока не закроешь программу
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
 
 
namespace Console_Parser
{
    class Program
    {
 
        static void Main(string[] args)
        {
            
            Console.WriteLine("Begin work");
            Parser WorkParser = new Parser();
            Console.WriteLine("Connect to url");
           //////// WorkParser.ParseLink(@"http://www.057.ua/dosug/446/");
            Console.WriteLine("Begin Parse");
            foreach (string link in WorkParser.GetUrls(@"http://www.057.ua/dosug/446"))
            {
                WorkParser.ParseLink(string.Concat(@"http://www.057.ua", link));
            }
            Console.WriteLine("Parse done");
            Console.WriteLine("Saving to file");
            Console.WriteLine("WorkDone");
            Console.WriteLine("To Exit Please enter -q-");
            Console.ReadKey();
        }
    }
}
если я коментирую парсинг первой странички что бы начинало из цикла со второй и атк далее,то парсит только вторую страничку пока не остановишь программу

Добавлено через 17 часов 47 минут
Разобрался,дело пошло,парсит,но сохраняет по 5 или больше копий информации из каждой страницы.
0
200 / 168 / 38
Регистрация: 21.10.2011
Сообщений: 178
07.08.2012, 13:25 5
Очевидно, что какой-то из ваших циклов отрабатывает лишние разы. Это прилично усложняет жизнь, да и вас путает.
Хотя бы присмотритесь к HtmlNodeCollection C, внутри прохода по которой у нас вложенный цикл по коллекции HtmlNodeCollection Names. Да и всё это крутится в цикле в мэйне, где идет обход страниц...
Однозначно, количество циклов надо уменьшать. Разберетесь с этим - тогда и проблема пропадет сама собой
+ ещё в методе Save чтот непорядок: лист загоняем в массив, который уже записываем в файл
Цитата Сообщение от Forzametal Посмотреть сообщение
Разобрался,дело пошло,парсит,но сохраняет по 5 или больше копий информации из каждой страницы.
Покажите, что было не так и какой xpath в итоге подошел?
1
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
07.08.2012, 13:44  [ТС] 6
Вот это подошел
HtmlNodeCollection Names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//table//tr//td[@valign='top']//h2");
Немного не понял,какой именно из циклов,а сохранение что не так?
Если можете , пожалуйста хPath http://www.057.ua/dosug/full/22089
адрес телефон мыло сайт время работы,как их вытащить?
Вложения
Тип файла: rar Console_Parser+strani4kiopisanie111.rar (162.2 Кб, 25 просмотров)
0
200 / 168 / 38
Регистрация: 21.10.2011
Сообщений: 178
07.08.2012, 15:37 7
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
private const string Shortulr = "http://www.057.ua";
public void ParseLink(string url)
{
    var doc = new HtmlDocument();
    doc.LoadHtml(LoadWebPage(url)); //загружаем текущую страницу
 
    var names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//table//tr//td[@valign='top']//h2"); //список названий
    if (names == null) return;
            
    foreach (var name in names)
    {
        try
        {
            var fullDescriptionPath = name.ChildNodes["a"].Attributes["href"].Value; //получаем ссылку на полное описание
 
            var document = new HtmlDocument();
            document.LoadHtml(LoadWebPage(Shortulr + fullDescriptionPath)); //загружаем полное описание
 
            //get address
            var nodeAddress = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[@bgcolor='#FFFFFF'][text()='Адрес:']");
            //get phone
            var nodePhone = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[text()='Телефон:']");
            //get site
            var nodeSite = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[@bgcolor='#FFFFFF'][text()='Сайт:']");
 
            Save(new AddressNames
            {
                Name = name.InnerText,
                Address = nodeAddress == null ? "" : nodeAddress.SelectSingleNode(@"..//td//strong").InnerText,
                Phone = nodePhone == null ? "" : nodePhone.SelectSingleNode(@"..//td//strong").InnerText,
                Site = nodeSite == null ? "" : nodeSite.SelectSingleNode(@"..//td//strong").InnerText
            });
        }
        catch
        {
        }                
    }            
}
 
private static void Save(AddressNames t)
{
    using (var sw = File.AppendText(@"test.txt"))
    {
        sw.WriteLine("{0}\t{1}\t{2}\t{3}", t.Name, t.Address, t.Phone, t.Site);
    }
}
 
//класс справочника адресов
private class AddressNames
{
    public string Name;
    public string Address;
    public string Site;
    public string Phone;
    public string WorkHours;
    //so on
}
Остальное не менял. Наверно можно и попроще. С AgilityPack впервые работаю
1
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
07.08.2012, 16:31  [ТС] 8
Спасибо шяс попробую

Добавлено через 39 минут
Работает.Но парсит первую страничку дважды,если её закоментить то вторую страничку дважды.
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HtmlAgilityPack;
using System.Net;
using System.IO;
 
namespace Console_Parser
{ 
    class Parser
    {
        string url = "http://www.057.ua/dosug/446";
        // Свойство класса 
       public string URL 
        { 
            set { url = value;}
            get { return url;}
        }
        public static string LoadWebPage(string url)// метод загрузки всех страниц
        {
            try
            {
                WebRequest reqGET = System.Net.WebRequest.Create(url);
                System.Net.WebResponse resp = reqGET.GetResponse();
                Stream stream = resp.GetResponseStream();
                StreamReader sr = new StreamReader(stream, Encoding.GetEncoding(65001));
                string s = sr.ReadToEnd();
                return s;
            }
            catch
            {
                return string.Empty;
            }
        }
        private const string Shortulr = "http://www.057.ua";
        public void ParseLink(string url)
        {
            var doc = new HtmlDocument();
            doc.LoadHtml(LoadWebPage(url)); //загружаем текущую страницу
 
            var names = doc.DocumentNode.SelectNodes(@".//*[@id='all_body']//table//tr//td[@valign='top']//h2"); //список названий
            if (names == null) return;
 
            foreach (var name in names)
            {
                try
                {
                    var fullDescriptionPath = name.ChildNodes["a"].Attributes["href"].Value; //получаем ссылку на полное описание
 
                    var document = new HtmlDocument();
                    document.LoadHtml(LoadWebPage(Shortulr + fullDescriptionPath)); //загружаем полное описание
 
                    //get address
                    var nodeAddress = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[@bgcolor='#FFFFFF'][text()='Адрес:']");
                    //get phone
                    var nodePhone = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[text()='Телефон:']");
                    //get site
                    var nodeSite = document.DocumentNode.SelectSingleNode(@".//*//table//tr//td[@bgcolor='#FFFFFF'][text()='Сайт:']");
 
                    Save(new AddressNames
                    {
                        Name = name.InnerText,
                        Address = nodeAddress == null ? "" : nodeAddress.SelectSingleNode(@"..//td//strong").InnerText,
                        Phone = nodePhone == null ? "" : nodePhone.SelectSingleNode(@"..//td//strong").InnerText,
                        Site = nodeSite == null ? "" : nodeSite.SelectSingleNode(@"..//td//strong").InnerText
                    });
                }
                catch
                {
                }
            }
        }
 
        private static void Save(AddressNames t)
        {
            using (var sw = File.AppendText(@"E:\Projects\Parser\Console_Parser\1.csv"))
            {
                sw.WriteLine("{0}\t{1}\t{2}\t{3}", t.Name, t.Address, t.Phone, t.Site);
            }
        }
 
        //класс справочника адресов
        private class AddressNames
        {
            public string Name;
            public string Address;
            public string Site;
            public string Phone;
            public string WorkHours;
            //so on
        }
 
      public IEnumerable<string> GetUrls(string url ="") // Метод GetUrls - находит "пейджер" который содержит ссылки и получает их( параметр url модержит информацию о странице - её адрес)
        {
            if (url == "") // точка остановы (отладка)
            {
                url = this.url;
            }
                HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();// новый документ HtmlDocument
                doc.LoadHtml(LoadWebPage(url));// загружаем страницу из параметра url
                foreach (HtmlNode link in doc.GetElementbyId("paginationControl").ChildNodes)// циклом перебираем содержимое "paginationControl"/ChildNodes - потомок экземпляра объекта 
                {
                    if (link.Name == "a")// если содержит атрибут "a"
                    {
                        yield return link.GetAttributeValue("href", string.Empty);//возврашает все что содержит атрибут  "href";yield сообщает компилятору, что метод, в котором оно содержится, является блоком итератора.Итерация - Итерация в программировании — организация обработки данных, при которой действия повторяются многократно, не приводя при этом к вызовам самих себя;string.Empty - Чтобы проверить, равно ли значение строки null или String.Empty
                    }
                }
          // Отладка висуал студио .
            
        }
 
    }
}
Добавлено через 12 минут
и из некоторых кафе не вытягивает инфу адрес телефон сайт
0
200 / 168 / 38
Регистрация: 21.10.2011
Сообщений: 178
07.08.2012, 16:38 9
Цитата Сообщение от Forzametal Посмотреть сообщение
и из некоторых кафе не вытягивает инфу адрес телефон сайт
Я же не делал универсальный парсер. Я показал, в какую сторону двигаться
//Писал xpath по двум страницам образца. Возможно на других страницах другие аттрибуты этих нод. Или же таких нод несколько находится. Надо собрать статистику, найти закономерности и применить ко всему этому один xpath

Не вникая в код, как вариант, для избавления от дубликатов могу предложить
C#
1
foreach (var name in names.Distinct())
По идее надо бы написать какую-нибуль коллекцию классов, в неё добить инфу со всех страниц, применить к ней дистинкт и сорт. И нормально вывести
2
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
07.08.2012, 19:54  [ТС] 10
Понял,большое спасибо)Буду пробовать,результаты выложу сюда.

Добавлено через 2 часа 22 минуты
работает,дубли убирает но 2ю страничку все равно двыжды парсит и её не убирает
1
FireFenix
07.08.2012, 20:29 11
Мой вариант

Выводит в итоге:
HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Наименование:кафе Cinema, доставка обедов, заказ пиццы, суши, десерты, торты на заказ
Адрес:улица Пушкинская, 22
Сайт:http://www.cinema-cafe.com.ua, http://vk.com/cinema.caffee, http://www.face
book.com/Cinema.Caffee
Телефон:758-55-88, +380 (63) 225-57-77
Емеил:info@cinema-cafe.com.ua
Skype:
Время работы:10 00 - 23 00
 
Наименование:FASHION COFFEE, boutique Харьков
Адрес:улица Сумская, 77/79
Сайт:
Телефон:750-60-44, +380 (99) 700-17-76
Емеил:fcoffee@ymail.com
Skype:fashioncoffee1
Время работы:с 9:00 до 19:00
 
Наименование:РК 24
Адрес:улица Героев Труда, 9, ТРЦ Дафи, 3-этаж
Сайт:http://rk24.com.ua/
Телефон:728-19-47
Емеил:
Skype:
Время работы:круглосуточно
 
Наименование:TACO- Доставка мексиканской кухни
Адрес:
Сайт:http://taco.com.ua
Телефон:758-90-90
Емеил:taco.kh@mail.ru
Skype:
Время работы:10.00 - 22.00
P.S. привет с чатика sc2tv
Вложения
Тип файла: rar Console_Parser+strani4kiopisanie111.rar (85.3 Кб, 52 просмотров)
FireFenix
07.08.2012, 20:50 12
Единственное нужно поменять вывод в консоль на вывод в файл, думаю с этим проблем не будет =)
2 / 2 / 0
Регистрация: 02.06.2012
Сообщений: 34
09.08.2012, 10:56  [ТС] 13
Оо спасибо,тоже вариант)))
0
09.08.2012, 10:56
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
09.08.2012, 10:56
Помогаю со студенческими работами здесь

Сохранение несколько StringGrid в один CSV файл
Имеется код (не мой); void __fastcall TForm2::Button2Click(TObject *Sender) {...

Парсинг базы данных и сохранение результата в отдельный файл
Всем привет! Помогите пожалуйста. Есть БД (mysql), нужно спарсить из нее одну таблицу, и по...

Ненужная строка при экспорте текста в CSV-файл
Как избавиться от второй строчки?(на скриншоте) $CSVfileOld=&quot;F:\Практика\user.csv&quot; #переменная...

Парсинг странички
Приветствую товарищи. У меня встал вопрос :D В общем суть, есть сайт MAL, так как я новичек в...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru