2017-05-27 85 views
0

基於之前編寫的code snippet,我現在試圖將多個圖像從某個subreddit一次存儲到本地目錄中。我的問題是,我無法讓我的LINQ語句正常工作。我也不想下載縮略圖這就是爲什麼我看了看在HTML頁面和發現,我的目標是獲取鏈接隱藏在5級href屬性中:LINQ中的System.NullReferenceException

(...) 
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")) 

可悲的是它拋出一個error指出

Object reference not set to an instance of an object 

現在好了,我知道爲什麼它不是w ^但我仍然不知道如何重寫這一行,因爲我對Lambda表達式還是比較新的。說實話,我真的不知道爲什麼我第一次得到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

更好的方法,您的問題是使用[JSON API(https://開頭WWW。 reddit.com/r/Jessica_Clements/.json)而不是解析HTML。 – Nasreddine

回答

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()?.。如果從GetParent()返回null,則停止該術語的執行。它被稱爲Null Conditional Operator或「貓王操作員」,因爲它可以被看作是雙眼三頭髮。如果執行因空值而停止,則?? false將給出默認值。

但是,如果你打算解析HTML代碼,你一定要看看Html Agility Pack (HAP)

+0

我有一個新想法:我如何交換兩個Where語句?那樣我不能確保這個鏈接不可能是空的?我現在是移動的,所以我不能檢查是否是真的。 – Stefan

+0

是的,完全正確。跳過空檢查然後去elvis操作員。或者,使用'String.Equals(link,「...」)'。通過不使用變量'link'來調用方法,你不能運行NullRefs – Waescher

1

,如果你想獲得的所有鏈接指向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(); 
相關問題