2017-10-31 18 views
0

私は、Wikipediaから幾つかの地理的データを取得する単純なスクレーパーを作成して、.NETテクノロジーとC#を学びたいと考えています。LINQ + XMLを使用してWebサイトをスクラブする

public IEnumerable<string> GetLinkToAllCountries() 
{ 

    return from node in XElement.Load(_URL.AbsoluteUri).Elements("body").Descendants() 
      where node.Name.LocalName == "a" 
          && node.Parent.Name.LocalName == "td" 
          && node.Parent.Parent.Name.LocalName == "tr" 
          && node.Attribute("href") != null 
          && node.Attribute("title") != null 
           select _URL.Scheme + "//" + _URL.Host + node.Attribute("href").Value; 

} 

これは正常に動作し、すべての国のWikiページへのリンクのリストを返します。

まず、私はthisウィキペディアのサイトからテーブルに国へのすべてのリンクを返します。このメソッドを作成しました。第二に、私は各国のページを訪問し、資本を取得したい。

私は似たような書きましたが、私はそれを動作させることはできません。

public IEnumerable<string> ListOfCapitals() { 

    var links = GetLinkToAllCountries(); 

    return from link in links 
      from node in XElement.Load(link).Elements("body").Descendants() 
      where node.Name.LocalName == "a" 
       && node.Parent.Name == "td" 
       && node.Attribute("title") != null 
      select node.Attribute("title").Value; 
} 

それは首都をリストしていない、およびVisual Studioは、System.Threadingに、いくつかの組立ポインタを作るようです。私はたぶん作業負荷のために非同期のものを書くべきでしょうか(200のWebサイトを訪問し、それぞれからデータを取得しています)?もし私がここで何らかの規則に違反していなければ、そのアプローチについての一般的なフィードバックも大好きです。ありがとう!

答えて

0

私はこれを行う方法の最善の方法は、TPLていると思う:リファクタリング

https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl

- 以下のクラスを考える:

public class WebScrapper 
{ 
    public IEnumerable<string> GetLinkToAllCountries(Uri uri) 
    { 
     return from node in XElement.Load(uri.AbsoluteUri).Elements("body").Descendants() 
      where node.Name.LocalName == "a" 
        && node.Parent.Name.LocalName == "td" 
        && node.Parent.Parent.Name.LocalName == "tr" 
        && node.Attribute("href") != null 
        && node.Attribute("title") != null 
      select uri.Scheme + "://" + uri.Host + node.Attribute("href").Value; 

    } 

    public IEnumerable<string> ListOfCapitals(string link) 
    { 
     return from node in XElement.Load(link).Elements("body").Descendants() 
      where node.Name.LocalName == "a" 
        && node.Parent.Name == "td" 
        && node.Attribute("title") != null 
      select node.Attribute("title").Value; 
    } 
} 

あなたは、次のようなものを持つことができます

 var webScrapper = new WebScrapper(); 

     var countryLinks = 
      webScrapper.GetLinkToAllCountries(
       new Uri("https://en.wikipedia.org/wiki/List_of_countries_and_dependencies_by_population")); 

     var capitals = countryLinks 
      .AsParallel() 
      .WithDegreeOfParallelism(Convert.ToInt32(Math.Ceiling(Environment.ProcessorCount * 0.75))) 
      .SelectMany(s => webScrapper.ListOfCapitals(s)) 
      .ToList(); 

WithDegreeOfParallelism -h0クエリを処理するために使用される多くのタスクを同時に実行します。

また、XElement.Load(uri.AbsoluteUri)の依存関係は、GetLinkToAllCountriesXElement.Load(link)であり、ListOfCapitalsになります。私はこれをリファクタリングして、抽象化のレイヤーがあるようにしました。その方法で、linqクエリはモックでユニットテストできました。

+0

非常に涼しい。これらの気の利いた並行した呼び出しと他の非同期呼び出しをさらに掘り起こす必要があります。あなたはプロセッサの時間のいくつかの要因の量の詮索を使用する部分で詳しく説明できますか? 明日あなたの解決策を試してみましょう! – Aphex

関連する問題