如何從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. 使用de Image 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張圖片。

下載圖像時,有時可能會失敗,因此我建議您使用Polly實現重試模式

Obs¹ :WebClient不支持並行操作,因此我為每個圖像URL創建一個。



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow