здравствуйте, не пугайтесь что тут там много текста, 80% написанного код занял)) с недавних пор учу шарп и вот в качестве тренировки пытаюсь парсить данные с аск.фм. собвственно вот то, что получилось:
класс отдельный класс для парса:
Код:
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
namespace WindowsFormsApplication15
{
class WebSiteParser
{
public static Task<ConcurrentBag<string>> RequestToSite(int firstPageNumber = 1, int lastPageNumber = 28)
{
var cookieContaner = new CookieContainer();
var newReg = new Regex("<a href=\"/(.*)\" class=\"stream-profile-container\">");
ThreadPool.SetMinThreads(9, 8);
//ThreadPool.SetMaxThreads(10, 28);
var parent = new Task<ConcurrentBag<string>>(() =>
{
var results = new ConcurrentBag<string>();
var list = Enumerable.Range(firstPageNumber, (lastPageNumber - firstPageNumber + 1));
foreach (var par in list)
{
new Task((page) =>
{
Debug.WriteLine("ThreadId={0}", Thread.CurrentThread.ManagedThreadId);
var nextOneResult = new List<string>();
var request = (HttpWebRequest)WebRequest.Create(String.Format(
@"http://ask.fm/likes/populiarnii/question/118637001075/people/?page={0}", page));
request.UserAgent = "Chrome";
request.CookieContainer = cookieContaner;
string responsestring = null;
using (var reader = new StreamReader(request.GetResponse().GetResponseStream()))
responsestring = reader.ReadToEnd();
var matches = newReg.Matches(responsestring);
if (matches.Count >= 0)
{
for (int i = matches.Count - 1, w = 1; i > -1; i--, w++)
nextOneResult.Add(matches[i].Groups[1].ToString());
for (int i = 0; i < nextOneResult.Count; i++)
results.Add(nextOneResult[i]);
}
},par, TaskCreationOptions.AttachedToParent).Start();
}
return results;
});
parent.Start();
return parent;
}
}
}
ну и запуск его:
Код:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
namespace WindowsFormsApplication15
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private async void button1_Click(object sender, EventArgs e)
{
listBox1.Items.Clear();
var sw = Stopwatch.StartNew();
var res = await WebSiteParser.RequestToSite(1, 28);
sw.Stop();
var time = sw.Elapsed.TotalSeconds;
label1.Text = time.ToString();
foreach (var result in res)
{
listBox1.Items.Add(result);
}
label2.Text += listBox1.Items.Count;
}
}
}
ссылка на проект: [Ссылки могут видеть только зарегистрированные пользователи. ]
дело в том что тут 28 страниц сайта обрабатываются в тасках(в четырёх потоках, т.к. 4 ядра у компа). как мне можно сделать парсинг в стольких потоках, сколько страниц? потому что в 4 потоках 28 страниц парсятся за 13 секунд, а если в дальнейшем у меня будет по 10К страниц?) поэтому прошу вашей помощи. так же делал с помощью одного потока используя библиотеку xNet:
Код:
using xNet.Net;
static CookieDictionary cook = new CookieDictionary();
string[] GET_1()//список лайкнувших
{
List<string> f_list = new List<string>();
var request = new HttpRequest();
request.UserAgent = HttpHelper.ChromeUserAgent();
request.Cookies = cook;
Regex newReg = new Regex("<a href=\"/(.*)\" class=\"stream-profile-container\">");
int P_n = 1;
while (true)
{
HttpResponse response = request.Get(string.Format("http://ask.fm/likes/populiarnii/question/118637001075/people/?page={0}", P_n));
P_n++;
var z = response.ToString();
MatchCollection matches = newReg.Matches(z);
if (matches.Count <= 0)
break;
for (int i = matches.Count - 1, w = 1; i > -1; i--, w++)
f_list.Add(matches[i].Groups[1].ToString());
}
return f_list.ToArray();
}
private void button1_Click(object sender, EventArgs e)
{
var sw = Stopwatch.StartNew();
listBox1.Items.AddRange(GET_3());
label1.Text += listBox2.Items.Count.ToString();
sw.Stop();
Debug.WriteLine("Execution time: {0}", sw.Elapsed.TotalSeconds);
var ae = sw.Elapsed.TotalSeconds;
label8.Text = ae.ToString();
}
Последний раз редактировалось VeTaL_UA; 17.05.2015 в 04:09.
через Thread создать ваши 28 потоков и запустить, но мне кажется скорости это не предаст особенно если комп слабый, так как выделение памяти это самый трудоемкий процесс
________________
Хотите как то отблагодарить за помощь?
Не стесняйтесь нажимайте "Спасибо" Для просмотра ссылок или изображений в подписях, у Вас должно быть не менее 10 сообщение(ий). Сейчас у Вас 0 сообщение(ий).
Делаю программы на заказ, по всем вопросам в скайп: Ginrey2
создайте отдельную процедуру и назовите например Parse, в аргументах можете указать нужную вам ссылку, например
Parse(string Url)
{
//тело самой процедуры
}
а дальше через цикл создавать потоки и запускать их
for(int i=0; i < 1; i++)
{
Thread thr = new Thread(delegate() {Parse("http://vk.com/id"+i.ToString()); });
thr.Start();
}
Привел самый банальный пример. URL так же выдуманный, думаю сами сможете сообразить использовать свои ссылки. в цикле создается 1 поток, поменяйте значение на желаемое для любого их кол-ва. ну и не забудьте добавить using System.Threading;
________________
Хотите как то отблагодарить за помощь?
Не стесняйтесь нажимайте "Спасибо" Для просмотра ссылок или изображений в подписях, у Вас должно быть не менее 10 сообщение(ий). Сейчас у Вас 0 сообщение(ий).
Делаю программы на заказ, по всем вопросам в скайп: Ginrey2
я пробовал всё это, но не получалось правильно запустить это. можете или в первом или во втором коде это сделать? выше же я привёл 2 своих готовых способа парсинга
Добавлено через 3 минуты
Цитата:
string[] GET_3()//список лайкнувших
{
List<string> f_list = new List<string>();
var request = new HttpRequest();
request.UserAgent = HttpHelper.ChromeUserAgent();
request.Cookies = cook;
Regex newReg = new Regex("<a href=\"/(.*)\" class=\"stream-profile-container\">");
int P_n = 1;
while (true)
{
HttpResponse response = request.Get(string.Format("http://ask.fm/likes/populiarnii/question/118637001075/people/?page={0}", P_n));
P_n++;
var z = response.ToString();
MatchCollection matches = newReg.Matches(z);
if (matches.Count <= 0)
break;
for (int i = matches.Count - 1, w = 1; i > -1; i--, w++)
f_list.Add(matches[i].Groups[1].ToString());
}
return f_list.ToArray();
}
private void button1_Click(object sender, EventArgs e)
{
var sw = Stopwatch.StartNew();
for (int i = 0; i < 25; i++)
(new Thread(new ThreadStart(GET_3))).Start();
//listBox2.Items.AddRange(GET_3());
label6.Text += listBox2.Items.Count.ToString();
sw.Stop();
var ae = sw.Elapsed.TotalSeconds;
label8.Text = ae.ToString();
}
вот так делаю, но у меня ошибка - Ошибка 1 string[] WindowsFormsApplication1.Enter.GET_3()" : недопустимый тип возвращаемого значения. как исправить?
Последний раз редактировалось ИнХард; 24.03.2015 в 20:17.
Причина: Добавлено сообщение
сделайте процедуру, а не функцию - void
и внутри потока добавляйте в listbox или куда вам нужно список
________________
Хотите как то отблагодарить за помощь?
Не стесняйтесь нажимайте "Спасибо" Для просмотра ссылок или изображений в подписях, у Вас должно быть не менее 10 сообщение(ий). Сейчас у Вас 0 сообщение(ий).
Делаю программы на заказ, по всем вопросам в скайп: Ginrey2