На основе предыдущего кода, написанного ранее сниппет Сейчас я пытаюсь сохранить сразу несколько изображений из определенного поддредита в локальный каталог. Моя проблема в том, что я не могу заставить мой оператор LINQ работать правильно. Я также не хочу загружать уменьшенные изображения, поэтому я взглянул на HTML-страницу и обнаружил, что ссылки, которые я собираюсь получить, скрыты на уровне 5 в атрибуте href:

(...)
Level 1: <div class="content">...</div>
    Level 2: <div class="spacer">...</div>
        Level 3: <div class="siteTable">...</div>
            Level 4: <div class=" thing id-t3_6dj7qp odd  link ">...</div>                      
                Level 5: <a class="thumbnail may-blank outbound" href="href="http://i.imgur.com/jZ2ZAyk.jpg"">...</a>

Это была моя лучшая ставка в строке «???»:

.Where(link => Directory.GetParent(link).Equals(@"http://i.imgur.com"))

К сожалению, он выдает сообщение об ошибке который

 Object reference not set to an instance of an object

Ну, теперь я знаю, почему это не работает, но я до сих пор не знаю, как переписать эту строку, так как я все еще довольно плохо знаком с Lambda Expressions. Если честно, я действительно не знаю, почему я получил System.NullReferenceException во-первых, но не в следующей строке. Какая разница? Может быть, мой подход к этой проблеме вообще не очень хорошая практика, поэтому, пожалуйста, дайте мне знать, как я могу действовать дальше.

using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Net;
using HtmlAgilityPack;

namespace GetAllImages
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> imageLinks = new List<string>();

            // Specify Directory manually
            string dirName = "Jessica Clements";
            string rootPath = @"C:\Users\Stefan\Desktop";
            string dirPath = Path.Combine(rootPath, dirName);

            // Specify the subReddit manually
            string subReddit = "r/Jessica_Clements";
            string url = @"https://www.reddit.com/" + subReddit;

            try
            {
                DirectoryInfo imageFolder = Directory.CreateDirectory(dirPath);                

                HtmlDocument document = new HtmlWeb().Load(url);
                imageLinks = document.DocumentNode.Descendants("a")
                            .Select(element => element.GetAttributeValue("href", null))
                            .Where(???) 
                            .Where(stringLink => !String.IsNullOrEmpty(stringLink))
                            .ToList();

                foreach(string link in imageLinks)
                {
                    using (WebClient _wc = new WebClient())
                    {
                        _wc.DownloadFileAsync(new Uri(link), Path.Combine(dirPath, Path.GetFileName(link)));
                    }                        
                 }

            Console.WriteLine($"Files successfully saved in '{Path.GetFileName(dirPath)}'.");             

            }

            catch(Exception e)
            {
                while(e != null)
                {
                    Console.WriteLine(e.Message);
                    e = e.InnerException;
                }
             }

            if(System.Diagnostics.Debugger.IsAttached)
            {
                Console.WriteLine("Press any key to continue . . .");
                Console.ReadKey(true);
            }
        }
    }
}

Изменить . На всякий случай, если кто-то заинтересовался этим решением, в конце концов я так и сделал, используя ответы ниже:

HtmlDocument document = new HtmlWeb().Load(url);
imageLinks = document.DocumentNode.Descendants("a")
            .Select(element => element.GetAttributeValue("href", null))
            .Where(link => (link?.Contains(@"http://i.imgur.com") == true))
            .Distinct()
            .ToList();
0
間澤東雲 28 Май 2017 в 00:06

2 ответа

Лучший ответ

Учитывая, что эта строка выдает исключение:

.Where(link => Directory.GetParent(link).Equals(@"http://i.imgur.com"))

Я хотел бы убедиться, что link не является нулевым, и что результат GetParent(link) также не является нулевым. Так что вы могли бы сделать:

.Where(link => link != null && (Directory.GetParent(link)?.Equals(@"http://i.imgur.com") ?? false))

Обратите внимание на нулевую проверку и ?. после GetParent(). Этот останавливает выполнение термина, если null возвращается из GetParent(). Он называется нулевым условным оператором или «оператором Элвиса», поскольку он может быть увиденным как два глаза с вьющимися волосами. ?? false дает значение по умолчанию в случае, если выполнение было остановлено из-за нулевого значения.

Однако , если вы планируете анализировать HTML-код, вам определенно стоит взглянуть на Html Agility Pack (HAP).

2
Waescher 27 Май 2017 в 21:59

Если вы пытаетесь получить все ссылки, указывающие на http://i.imgur.com, вам нужно что-то как это

    imageLinks = document.DocumentNode.Descendants("a")
                .Select(element => element.GetAttributeValue("href", null))
                .Where(link => link?.Contains(@"http://i.imgur.com") == true)
                .ToList();
1
makison 27 Май 2017 в 22:07