Loading...

Във форума е въведено ограничение, което позволява на потребителите единствено да разглеждат публикуваните въпроси.

Svetlyo avatar Svetlyo 8 Точки

[C# "Basics"] Parse HTML с HTML Agility Pack

Здравейте колеги. Реших да си поиграя и да си напиша програма, която да обхожда даден блог по зададен Url и да прави списък с брой харесвания на постове и линковете към тях. Става дума за блог, който има следната структура на страниците : http://blog.somesite.com/page/1 ,2,3...n  .

За момента успях да си съчиня следното :

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HtmlAgilityPack;

namespace ParsingHTML
{
public partial class SiteScraper : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void ClickMeButton_Click(object sender, EventArgs e)
{
var getHtmlWeb = new HtmlWeb();
var document = getHtmlWeb.Load(InputTextBox.Text);
var aTags = document.DocumentNode.SelectNodes("//div[@id='datetag'] //a[position()=2]");
Dictionary<int, string> mydict = new Dictionary<int, string>();
string link;
string note;
int number;

if (aTags != null)
{
foreach (var aTag in aTags)
{
note = aTag.InnerHtml;
link = aTag.Attributes["href"].Value;
note = note.Replace(",", "");
note = note.Replace(" notes", "");
bool isNumber = Int32.TryParse(note, out number);
mydict.Add(number, link);

}

mydict = mydict.OrderByDescending(x => x.Key).ToDictionary(x => x.Key, x => x.Value);

foreach (KeyValuePair<int, string> kvp in mydict)
{
OutputLabel.Text += "- " + kvp.Key + " " + kvp.Value + "<br />";
}
}
}
}
}

 

Между другото, има ли някакъв  C# Syntax Highlighter във форума или някакъв друг вариант да си подреждам по-добре кода като го пиша тук? Не съм ползвал много форума до момента, съжалявам.

 

Това за момента успешно ми намира харесванията ("notes"), линка към тях и ми ги подрежда по брой харесвания.

За момента обаче имам следните проблеми и питания:

- как да обходя всички страници от блога

  • вариант а) ако не знам колко точно са
  • вариант б) ако знам, че са 123, например.

Крайният резултат искам да ми даде пак такъв списък, но с данни от всички страници, т.е. - ако например блога е с 3 страници, на първата пост 1 има 100 харесвания, на 2-рата пост 2 има 200 харесвания, а на третата пост 3 има 300 - да ми ги изкара във списък от най-голямото към най-малкото.

На мен за момента ми идват 2 идеи - или някак да наблъскам съдържанието на всички страници в 1 документ и после да си вадя нещата от там, или страница по страница да се добавят нещата в речника и накрая просто да си ги foreach-на, както до момента.

Ще съм благодарен, ако някой ми помогне с съвети/насоки! :)

 

 

Тагове:
0
Programming Basics 15/08/2014 01:32:27
Svetlyo avatar Svetlyo 8 Точки

Update:

Помислих още малко и успях да си реша някои от основните проблеми.

Обхождането на сайта във вариант б), когато знам броя на страниците го правя така:

for (int i = 1; i <= 123; i++)
{
url = string.Format("http://blog.somesite.com/page/{0}", i);
urls.Add(url);
}

и резултата си го записвам във лист.

После слагам всичко в един foreach цикъл и минавам през всички връзки.

В крайна сметка се отказах от речника, в полза на лист понеже ми хвърляше такъв Exception:

ArgumentException: An item with the same key has already been added.

 

За момента, кода изглежда така:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using HtmlAgilityPack;

namespace ParsingHTML
{
public partial class SiteScraper : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void ClickMeButton_Click(object sender, EventArgs e)
{
string url;
List<string> urls = new List<string>();
List<Tuple<int, string>> mylist = new List<Tuple<int, string>>();
string link;
string note;
int number;
for (int i = 1; i <= 123; i++)
{
url = string.Format("http://blog.somesite.com/page/{0}", i);
urls.Add(url);
}
var getHtmlWeb = new HtmlWeb();
foreach (var entry in urls)
{
var document = getHtmlWeb.Load(entry);
var aTags = document.DocumentNode.SelectNodes("//div[@id='datetag'] //a[position()=2]");

if (aTags != null)
{
foreach (var aTag in aTags)
{
note = aTag.InnerHtml;
link = aTag.Attributes["href"].Value;
note = note.Replace(",", "");
note = note.Replace(" notes", "");
bool isNumber = Int32.TryParse(note, out number);
mylist.Add(new Tuple<int, string>(number, link));

}
}
}

mylist = mylist.OrderByDescending(i => i.Item1).ToList();

foreach (var item in mylist)
{
OutputLabel.Text += "- " + item.Item1 + " " + item.Item2 + "<br />";
}
}
}
}

Все пак ще се радвам на предложения за оптимизация или други идеи! :)

0
15/08/2014 03:15:41
a_rusenov avatar a_rusenov 1103 Точки

Доста интересна задачка :). Ще може ли да качиш кода в pastebin или github, понеже тук много гадно се чете.

Иначе това, което искаш да направиш, ми прилича на web crawler. На твое място бих направил обхождането на блога рекурсивно, т.е. да влиза във всеки хиперлинк, който намери в текущата страница, после в хиперлинковете на страницата, към която предният хиперлинк я отвел, и т.н., докато страницата вече не е на блога. Естествено вече посетените ще ги пазиш някъде и ще правиш проверка да не се обхождат повторно. И така във всяка страница ще си събира информация за постовете, докато в един момент не се изчерпят всички страници. Тук го има и моментът, че ще изпуснеш страниците, които не са реферирани никъде, но пък и при Гугъл си е така..

За тази техника ти трябва да изпозлваш рекурсия. Ако имаш време и желание, погледни това видео - https://www.youtube.com/watch?v=YP9K7uAzoFA
0
16/08/2014 00:20:58
Можем ли да използваме бисквитки?
Ние използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Можете да се съгласите с всички или част от тях.
Назад
Функционални
Използваме бисквитки и подобни технологии, за да предоставим нашите услуги. Използваме „сесийни“ бисквитки, за да Ви идентифицираме временно. Те се пазят само по време на активната употреба на услугите ни. След излизане от приложението, затваряне на браузъра или мобилното устройство, данните се трият. Използваме бисквитки, за да предоставим опцията „Запомни Ме“, която Ви позволява да използвате нашите услуги без да предоставяте потребителско име и парола. Допълнително е възможно да използваме бисквитки за да съхраняваме различни малки настройки, като избор на езика, позиции на менюта и персонализирано съдържание. Използваме бисквитки и за измерване на маркетинговите ни усилия.
Рекламни
Използваме бисквитки, за да измерваме маркетинг ефективността ни, броене на посещения, както и за проследяването дали дадено електронно писмо е било отворено.