В настоящее время у нас есть веб-искатель для наших клиентов, у которых нет возможности предоставить нам xml файл. Список создается, поэтому мне нужно иметь более эффективный способ обхода этих сайтов. Логика сканера проста:
Pass in www.example.com/widgets
Store the html and pass it to crawler function
crawl widgets page 1
IF widgets page 1 is the end of their product list
stop
else
go to widgets page 2
Это повторяется для каждого сайта в очереди. Как вы можете видеть, если на сайте 1 есть 5000 продуктов, сайт 2 не может действовать до тех пор, пока он не будет выполнен. Что было бы лучшим способом для многопоточного потока, чтобы я мог ограничить количество запросов, которые я делаю для каждого сайта, но одновременно захватить несколько сайтов? Я попробовал Parallel.ForEach, но результат был очень спорадическим и непредсказуемым. В настоящее время мы справляемся с этим, когда "группы" магазинов блокируются и одновременно используют диспетчер задач Windows. вот пример кода:
foreach(site in ListofSites)
{
int page = 1;
bool continue_crawling = true;
while(continue_crawling)
{
HtmlDocument doc = new HtmlDocument();
var htmlWeb = new HtmlWeb();
htmlWeb.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
doc = htmlWeb.Load(URL + page);
string html = doc.DocumentNode.OuterHtml;
continue_crawling = ParseFile(html);
page++;
}
}
private bool Parse(string html)
{
//parse the file and see if we have enough data
return endofproduct;
}
Все HTTP-запросы С# пройдут через ServicePoint
для домена URL-адреса запроса. ServicePoint наследует ConnectionLimit
из ServicePointManager.DefaultConnectionLimit
. Значение по умолчанию - 2, в соответствии с "практикой хороших клиентов" RFC2616:
Однопользовательский клиент НЕ ДОЛЖЕН поддерживать более двух соединений с любым сервером или прокси.
Все, что переводится, заключается в том, что запуск 1 HTTP-запросов gazzilion для URL-адресов в том же домене будет отправлять только не более 2 HTTP-запросов, а другой не запускается, если только он не завершится. Для достижения более высокого уровня параллелизма вам необходимо увеличить лимит подключения ServicePoint для домена, представляющего интерес. Выполнение параллельного ввода-вывода с использованием потоков (включая PTL) довольно примитивно, но должно работать, если вы исправите ограничение. Разумеется, предпочтительнее использовать асинхронный ввод-вывод.