- Регистрация
- 31.10.2013
- Сообщения
- 1 190
- Благодарностей
- 791
- Баллы
- 113
Привет вам, дорогие форумчане!
Как и в предыдущей статье я буду рассказывать о том что интересно мне и в итоге попытаюсь заинтересовать и Вас!
Я люблю экспериментировать, изучать языки программирования, искать нестандартные технические решения. Всем, кто читал мою предыдущую конкурсную статью и не нашел в ней смысла, предлагаю не тратить свое драгоценное время на выяснение какой же континент я здесь пытаюсь открыть. Надеюсь, что кто-нибудь хоть как-то да оценит мои эксперименты.
И в этот раз моя любознательность завела меня в область параллельных вычислений и что с помощью них можно сделать.
Говоря параллельных вычислениях я подразумеваю те способы или методы, реализованные в языках программирования, которые позволяют выполнять определенные параллельно, независимо друг от друга операции. В противовес можно поставить последовательные операции, а самым наглядным примером будет последовательность выполнения задач в шаблоне и многопоточное выполнение шаблона.
В принципе мультизадачность очень серьезная и обширная тема, а мне бы хотелось рассказать конкретные моменты, которые действительно можно применить в программе, когда есть такая возможность или желание.
Иногда так бывает, что перед шаблоном стоит задача просто получать данные с интернет-ресурсов, а потом что-то с ними делать. Очень часто эти задачи однотипные и в основном повторяются если не в цикле то в многопотоке шаблона.
Допустим, мне нужно собрать данные с определенного сайта, перебирая страницы с 1 по N. Обязательным условием должна быть возможность не использовать браузер и это очень важно. Обычная логика будет завернуть запрос и обработку в цикл и подкорректировать логику для возможности работы шаблона в многопотоке, если страниц много.
В принципе это нормально, но я нашел альтернативное решение с использованием параллельных циклов C# Parallel.For и Parallel.ForEach.
Теперь я постараюсь описать работу одного из трех шаблонов, которые будут в приложении. Перед нами стоит задача «выпарсить» весь список сайтов по домену высшего уровня с сайта domaintyper.com.
Для начала нам нужно подготовить данные, которые мы будем использовать для параллельного цикла.
int threads = int.Parse(project.Variables["threads"].Value);
var proxy = project.Variables["proxy"].Value;
string url = project.Variables["url"].Value;
var path = project.Variables["path"].Value;
int start_page = int.Parse(project.Variables["start_page"].Value);
project.Variables["start_page"].Value = (start_page + threads).ToString();
var regex = new System.Text.RegularExpressions.Regex("(?<=<tr\\sclass=\"wsTR[^<]*?<td>[^<]*?</td>[^<]*?<td>)[^<]+");
List<int> emptypages = new List<int>();
List<string> rlist = new List<string>();
int lastpage = 0;
int extracted = 0;
threads – отвечает у нас за количество «потоков», то есть сколько параллельных запросов мы собираемся сделать за раз.
proxy – адрес прокси если вдруг кому захочется поэкспериментировать. Сразу же говорю, скорость будет относительно медленней, так как данный пример не предусматривает использования уникальных прокси для каждого запроса в отдельности, но в принципе это возможно.
url - является корневой ссылкой, его значение можете увидеть открыв шаблон.
path отвечает за путь к файлу куда мы будем дописывать список
start_page – номер страницы с которой мы будем продолжать скачивать.
List<int> emptypages будет собирать те номера страниц где не удалось по какой-то причине обнаружить нужные нам строки.
List<string> rlist – главный список, в который мы будем складывать все найденные на странице сайты.
lastpage будет сигнализировать о том что мы дошли до последней страницы и дальше делать запросы не нужно.
extracted покажет сколько мы нашли ссылок на странице
А вот и сам параллельный цикл.
System.Threading.Tasks.Parallel.For(start_page, start_page+threads, p => {
___var response = ZennoPoster.HttpGet(url: url+p.ToString(), proxy: proxy, Encoding:"UTF-8", Timeout: 60000);
___List<string> domains = regex.Matches(response).Cast<System.Text.RegularExpressions.Match>().Select(s=>s.Value).Where(s=>s!="").ToList();
___project.SendInfoToLog(domains.Count.ToString(), p.ToString());
___rlist.AddRange(domains);
___extracted += domains.Count;
___if(response.Contains("<div class=\"pagingDivDisabled\">Next</div>")){
______emptypages.Add(p);
______if(domains.Count > 0){
_________lastpage = p;
_________project.SendInfoToLog("lastpage", p.ToString());
______}
___}
___else{
______if(domains.Count <= 0)
_________emptypages.Add(p);
___}
});
Метод Parallel.For работает как обычный цикл от start_page до start_page+threads только метод, который передается третьим параметром будет выполняться параллельно для каждого итератора p.
В этом методе производится запрос по адресу url+p , вытаскиваются из ответа данные в список domains , а уже только после добавляем domains в результирующий - rlist.AddRange(domains) . Дальше идет определение, является ли наша страница последней и если нет, плюс добавляем в emptypages номер страницы, которая неудачно подгрузилась.
Завершение работы Parallel.ForEach означает что мы скачали все страницы, обработали их, собрали все что можно в результирующие списки rlist и emptypages.
Все, что идет ниже параллельного цикла, это анализ, сохранение, логирование и вызов исключения в случае если emptypages хранит в себе не ту страницу которую стоило ожидать последней на сайте.
В итоге мы получаем отдельный сниппет, который собирает для нас данные в параллельном режиме в один поток зеннопостера.
Два других шаблона работают по тому же принципу, но выполняют другие задачи.
ahrefs.com(top_domains).xmlz – может работать со списком прокси. Рекомендуемое число потоков от 50 до 1000;
gplusparser2.xmlz – скачивает аватарки на диск по ссылкам из уже подготовленного списка. Ставьте смело 10 000 потоков и смотрите что получится.
Вот и все. Удачи всем и спасибо за внимание!
Как и в предыдущей статье я буду рассказывать о том что интересно мне и в итоге попытаюсь заинтересовать и Вас!
Я люблю экспериментировать, изучать языки программирования, искать нестандартные технические решения. Всем, кто читал мою предыдущую конкурсную статью и не нашел в ней смысла, предлагаю не тратить свое драгоценное время на выяснение какой же континент я здесь пытаюсь открыть. Надеюсь, что кто-нибудь хоть как-то да оценит мои эксперименты.
И в этот раз моя любознательность завела меня в область параллельных вычислений и что с помощью них можно сделать.
Говоря параллельных вычислениях я подразумеваю те способы или методы, реализованные в языках программирования, которые позволяют выполнять определенные параллельно, независимо друг от друга операции. В противовес можно поставить последовательные операции, а самым наглядным примером будет последовательность выполнения задач в шаблоне и многопоточное выполнение шаблона.
В принципе мультизадачность очень серьезная и обширная тема, а мне бы хотелось рассказать конкретные моменты, которые действительно можно применить в программе, когда есть такая возможность или желание.
Иногда так бывает, что перед шаблоном стоит задача просто получать данные с интернет-ресурсов, а потом что-то с ними делать. Очень часто эти задачи однотипные и в основном повторяются если не в цикле то в многопотоке шаблона.
Допустим, мне нужно собрать данные с определенного сайта, перебирая страницы с 1 по N. Обязательным условием должна быть возможность не использовать браузер и это очень важно. Обычная логика будет завернуть запрос и обработку в цикл и подкорректировать логику для возможности работы шаблона в многопотоке, если страниц много.
В принципе это нормально, но я нашел альтернативное решение с использованием параллельных циклов C# Parallel.For и Parallel.ForEach.
Теперь я постараюсь описать работу одного из трех шаблонов, которые будут в приложении. Перед нами стоит задача «выпарсить» весь список сайтов по домену высшего уровня с сайта domaintyper.com.
Для начала нам нужно подготовить данные, которые мы будем использовать для параллельного цикла.
int threads = int.Parse(project.Variables["threads"].Value);
var proxy = project.Variables["proxy"].Value;
string url = project.Variables["url"].Value;
var path = project.Variables["path"].Value;
int start_page = int.Parse(project.Variables["start_page"].Value);
project.Variables["start_page"].Value = (start_page + threads).ToString();
var regex = new System.Text.RegularExpressions.Regex("(?<=<tr\\sclass=\"wsTR[^<]*?<td>[^<]*?</td>[^<]*?<td>)[^<]+");
List<int> emptypages = new List<int>();
List<string> rlist = new List<string>();
int lastpage = 0;
int extracted = 0;
threads – отвечает у нас за количество «потоков», то есть сколько параллельных запросов мы собираемся сделать за раз.
proxy – адрес прокси если вдруг кому захочется поэкспериментировать. Сразу же говорю, скорость будет относительно медленней, так как данный пример не предусматривает использования уникальных прокси для каждого запроса в отдельности, но в принципе это возможно.
url - является корневой ссылкой, его значение можете увидеть открыв шаблон.
path отвечает за путь к файлу куда мы будем дописывать список
start_page – номер страницы с которой мы будем продолжать скачивать.
List<int> emptypages будет собирать те номера страниц где не удалось по какой-то причине обнаружить нужные нам строки.
List<string> rlist – главный список, в который мы будем складывать все найденные на странице сайты.
lastpage будет сигнализировать о том что мы дошли до последней страницы и дальше делать запросы не нужно.
extracted покажет сколько мы нашли ссылок на странице
А вот и сам параллельный цикл.
System.Threading.Tasks.Parallel.For(start_page, start_page+threads, p => {
___var response = ZennoPoster.HttpGet(url: url+p.ToString(), proxy: proxy, Encoding:"UTF-8", Timeout: 60000);
___List<string> domains = regex.Matches(response).Cast<System.Text.RegularExpressions.Match>().Select(s=>s.Value).Where(s=>s!="").ToList();
___project.SendInfoToLog(domains.Count.ToString(), p.ToString());
___rlist.AddRange(domains);
___extracted += domains.Count;
___if(response.Contains("<div class=\"pagingDivDisabled\">Next</div>")){
______emptypages.Add(p);
______if(domains.Count > 0){
_________lastpage = p;
_________project.SendInfoToLog("lastpage", p.ToString());
______}
___}
___else{
______if(domains.Count <= 0)
_________emptypages.Add(p);
___}
});
Метод Parallel.For работает как обычный цикл от start_page до start_page+threads только метод, который передается третьим параметром будет выполняться параллельно для каждого итератора p.
В этом методе производится запрос по адресу url+p , вытаскиваются из ответа данные в список domains , а уже только после добавляем domains в результирующий - rlist.AddRange(domains) . Дальше идет определение, является ли наша страница последней и если нет, плюс добавляем в emptypages номер страницы, которая неудачно подгрузилась.
Завершение работы Parallel.ForEach означает что мы скачали все страницы, обработали их, собрали все что можно в результирующие списки rlist и emptypages.
Все, что идет ниже параллельного цикла, это анализ, сохранение, логирование и вызов исключения в случае если emptypages хранит в себе не ту страницу которую стоило ожидать последней на сайте.
В итоге мы получаем отдельный сниппет, который собирает для нас данные в параллельном режиме в один поток зеннопостера.
Два других шаблона работают по тому же принципу, но выполняют другие задачи.
ahrefs.com(top_domains).xmlz – может работать со списком прокси. Рекомендуемое число потоков от 50 до 1000;
gplusparser2.xmlz – скачивает аватарки на диск по ссылкам из уже подготовленного списка. Ставьте смело 10 000 потоков и смотрите что получится.
Вот и все. Удачи всем и спасибо за внимание!
- Тема статьи
- Другое
- Номер конкурса статей
- Третий конкурс статей
Вложения
-
1,2 МБ Просмотры: 1 253
Для запуска проектов требуется программа ZennoPoster или ZennoDroid.
Это основное приложение, предназначенное для выполнения автоматизированных шаблонов действий (ботов).
Подробнее...
Для того чтобы запустить шаблон, откройте нужную программу. Нажмите кнопку «Добавить», и выберите файл проекта, который хотите запустить.
Подробнее о том, где и как выполняется проект.
Последнее редактирование: