どのように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. 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;
    }
}

そして、あなたはそのように使うことができます:

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;
    }
}

そして、178枚の画像がダウンロードされました。

画像がダウンロードされていると、失敗することがあるので、 Pollyを使ってRetryパターンを実装することをお勧めします。

Obs¹ :WebClientはパラレル操作をサポートしていないので、イメージURLごとに1つずつ作成します。




ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ