.namespace CenterCLR
{
.class public ILSupportSampleClass
{
.method public static int32
Compute(int32 a, int32 b) cil managed
{
ldarg.0
ldarg.1
add
ret
}
}
}
C#側からはMethodImpl属性で参照可能にします。
namespace CenterCLR
{
public class ILSupportSampleClass
{
[MethodImpl(MethodImplOptions.ForwardRef)]
public static extern int Compute(int a, int b);
}
}
Windows PhoneもWinRTベースの環境と、続々と出荷されるWindows Phone 8ベースの端末(何故か国内では発売されていない。「何故か」w)のおかげで、すっかりWinRTも浸透してきたようです。
(写真に登場するLumia 1520とプロ生ちゃんはフィクションであり、この記事とは無関係ですw)
以前に作ったスクレイピングのライブラリは、 「SgmlReader」と呼ばれるものをPortable Class Library化したものです。このライブラリは、「SGML」をパースしてXmlReader化するものですが、HTMLのDTDが添付されており、要するに「普通のHTMLパーサー」として使えるところがミソです。
これはNuBuildプロジェクトのダイアログですが、「Add Binaries To SubFolder」だけTrueに変えておきます。今回のパッケージには、Profile1のPCLとWinRT向けのPCLの2つのバージョンを入れ込むため、サブフォルダに配置するように指示します。あとはデフォルトのままです。
<?xml version="1.0" encoding="utf-16"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<!-- Required metadata -->
<id>CenterCLR.SgmlReader</id>
<version>2014.12.7.3</version>
<title>SgmlReader for Portable Class Library</title>
<summary>SgmlReader for Portable Class Library. SgmlReader most popular usage the "HTML" parser. (It's scraper!!)</summary>
<authors>Kouji Matsui</authors>
<description>SgmlReader for Portable Class Library.
SgmlReader is "SGML" markup language parser, and derived from System.Xml.XmlReader in .NET CLR.
But, most popular usage the "HTML" parser. (It's scraper!!)
/* Use SgmlReader in Html parse mode. */
XDocument document = SgmlReader.Parse(stream);
Done!</description>
<releaseNotes>2014.12.7.3:
Add 1 line parse method.
2014.12.7.2:
Direct handling the Stream class.
Initial parameter is set of Html parse mode.
2014.12.7.1:
Namespace changed "CenterCLR.Sgml".
More easy usage, HTML parse is default mode.
Native store app library included.
1.8.11.2014:
Initial release.</releaseNotes>
<projectUrl>https://github.com/kekyo/CenterCLR.SgmlReader.git</projectUrl>
<iconUrl>https://raw.githubusercontent.com/kekyo/CenterCLR.SgmlReader/master/CenterCLR.SgmlReader.100.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<licenseUrl>http://opensource.org/licenses/Apache-2.0</licenseUrl>
<copyright>Copyright (c) 2002, Microsoft Corporation; Copyright (c) 2007-2013, MindTouch; Copyright (c) 2014, Kouji Matsui</copyright>
<tags>SgmlReader Parser Portable HtmlReader Html Scraping</tags>
<!-- Optional metadata
<owners></owners>
<dependencies>
</dependencies>
<references></references>
-->
</metadata>
</package>
/// <summary>
/// 指定されたURLのHTMLを読み取って解析します。
/// </summary>
/// <param name="url">URL</param>
/// <returns>コンテンツ群のURL</returns>
private static async Task<IReadOnlyList<KeyValuePair<Uri, string>>> LoadFromAsync(Uri url)
{
using (var client = new HttpClient())
{
using (var stream = await client.GetStreamAsync(url).ConfigureAwait(false))
{
// SgmlReaderを使う
var sgmlReader = new SgmlReader(stream);
var document = XDocument.Load(sgmlReader);
// 郵便番号データダウンロードのサイトをスクレイピングする
// ターゲットは、html/body/div[id=wrap-inner]/div[id=main-box]/div[class=pad]/table/tbody/tr/td/a
// にあるhrefとなる。
// パースとトラバースまでワーカースレッドで実行しておく。
return
(from html in document.Elements("html")
from body in html.Elements("body")
from divWrapOuter in body.Elements("div")
let wrapOuter = GetAttribute(divWrapOuter, "id")
where wrapOuter == "wrap-outer"
from divWrapInner in divWrapOuter.Elements("div")
let wrapInner = GetAttribute(divWrapInner, "id")
where wrapInner == "wrap-inner"
from divMainBox in divWrapInner.Elements("div")
let mainBox = GetAttribute(divMainBox, "id")
where mainBox == "main-box"
from divPad in divMainBox.Elements("div")
let pad = GetAttribute(divPad, "class")
where pad == "pad"
from table in divPad.Elements("table")
from tbody in table.Elements("tbody")
from tr in tbody.Elements("tr")
from td in tr.Elements("td")
from a in td.Elements("a")
let href = GetAttribute(a, "href")
where href.EndsWith(".zip", StringComparison.OrdinalIgnoreCase) == true
let zipUrl = ParseUrl(url, href)
where zipUrl != null
let text = a.Value
where string.IsNullOrWhiteSpace(text) == false
select new KeyValuePair<Uri, string>(zipUrl, text)).
ToList();
}
}
}