Как загрузить все изображения с сайта на C # + HtmlAgilityPack?

.net c# html-agility-pack parsing

Вопрос

Я использую такие программы, как Teleport, HTTrack, Offline Explorer, DownThemAll и другие. Все фотографии найдены только - DownThemAll. Но у меня много страниц, с которыми вы хотите загрузить фотографии товаров. DownThemAll не подходит.

Я написал программу на C # + HtmlAgilityPack, но она не нашла все фотографии товаров.

В идеале я бы хотел:

  1. Программа загружает файл URLS.txt. В которых такие ссылки:

http://www.onlinetrade.ru/catalogue/televizori-c181/

http://www.onlinetrade.ru/catalogue/3d_ochki-c130/

и т.д

  1. Программа загружает на эти страницы все фотографии товаров.

Что вы посоветуете? Может быть, я ошибаюсь, чтобы написать код на C #?

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
WebClient wc = new WebClient();
string url = wc.DownloadString("http://www.onlinetrade.ru/catalogue/televizori-c181/");
doc.LoadHtml(url);

HtmlNodeCollection nodes = doc.DocumentNode.SelectNodes("//a[@class='catalog__displayedItem__columnFotomainLnk']/img");

if (nodes != null)
            {
                foreach (HtmlNode node in nodes)
                {                    
                    listBox1.Items.Add(node.Attributes["src"].Value);
                }
            }

Принятый ответ

Вы шли хорошо. В этом решении я использую LINQ и TPL.

На этом сайте используется разбиение на страницы, поэтому вы должны загружать все страницы, чтобы иметь возможность загружать изображения всех продуктов.

  1. Загрузка первой страницы (HtmlNode)
  2. Узнайте, сколько страниц этого каталога продуктов
  3. Загрузка других страниц (HtmlNode)

Затем у вас есть коллекция страниц

  1. Загрузите узлы img, которые вы хотите загрузить
  2. Создайте кортеж с URL-адресом изображения и новым экземпляром WebClient¹
  3. Загрузить изображение
public class ImageDownloader
{
    public void DownloadImagesFromUrl(string url, string folderImagesPath)
    {
        var uri = new Uri(url + "/?per_page=50");
        var pages = new List<HtmlNode> { LoadHtmlDocument(uri) };

        pages.AddRange(LoadOtherPages(pages[0], url));

        pages.SelectMany(p => p.SelectNodes("//a[@class='catalog__displayedItem__columnFotomainLnk']/img"))
             .Select(node => Tuple.Create(new UriBuilder(uri.Scheme, uri.Host, uri.Port, node.Attributes["src"].Value).Uri, new WebClient()))
             .AsParallel()
             .ForAll(t => DownloadImage(folderImagesPath, t.Item1, t.Item2));
    }

    private static void DownloadImage(string folderImagesPath, Uri url, WebClient webClient)
    {
        try
        {
            webClient.DownloadFile(url, Path.Combine(folderImagesPath, Path.GetFileName(url.ToString())));
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }

    private static IEnumerable<HtmlNode> LoadOtherPages(HtmlNode firstPage, string url)
    {
        return Enumerable.Range(1, DiscoverTotalPages(firstPage))
                         .AsParallel()
                         .Select(i => LoadHtmlDocument(new Uri(url + "/?per_page=50&page=" + i)));
    }

    private static int DiscoverTotalPages(HtmlNode documentNode)
    {
        var totalItemsDescription = documentNode.SelectNodes("//div[@class='catalogItemList__numsInWiev']").First().InnerText.Trim();
        var totalItems = int.Parse(Regex.Match(totalItemsDescription, @"\d+$").ToString());
        var totalPages = (int)Math.Ceiling(totalItems / 50d);
        return totalPages;
    }

    private static HtmlNode LoadHtmlDocument(Uri uri)
    {
        var doc = new HtmlDocument();
        var wc = new WebClient();
        doc.LoadHtml(wc.DownloadString(uri));

        var documentNode = doc.DocumentNode;
        return documentNode;
    }
}

И вы можете так использовать:

DownloadImagesFromUrl("http://www.onlinetrade.ru/catalogue/televizori-c181/", @"C:\temp\televizori-c181\images");

И затем было загружено 178 изображений.

При загрузке изображений иногда может произойти сбой, поэтому я предлагаю вам использовать шаблон Retry с помощью Polly .

Obs¹ : WebClient не поддерживает параллельную операцию, поэтому я создаю один для каждого URL- адреса изображения.



Related

Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему
Лицензировано согласно: CC-BY-SA with attribution
Не связан с Stack Overflow
Является ли этот КБ законным? Да, узнайте, почему