Quantcast
Channel: いげ太の日記
Viewing all articles
Browse latest Browse all 26

「実践 F#」の正誤表について

$
0
0

大変お待たせして申し訳ありません。書籍「実践 F#」の正誤表が公開されました。出版社サポート サイトで重要な訂正を、荒井さんのブログでさらなる訂正を公開している形となります。

すべての正誤情報を保存・印刷するには不便な格好での公開となり、重ねてお詫び申し上げます。つきましては、正誤情報をスクレイピングして以下画像のような HTML にまとめて整形する F# スクリプトをご用意いたしました。

F# スクリプトは以下の通りです。使用方法は、スクリプトの先頭のコメントに記載しております。よろしければお使いください。

(**
*                          PracticalFS.Errata.fsx
*                                by @igeta
*
* 書籍「実践 F#」の正誤表を取得する F# スクリプトです(以下、本スクリプト)。
*
* 本スクリプトは、Html Agility Pack ライブラリ(ライセンス:Ms-PL)を使用
* します。Html Agility Pack は、http://htmlagilitypack.codeplex.com/ から
* HtmlAgilityPack.1.4.0.zip をダウンロードして使用します。
*
* 本スクリプトを使用するには、まず適当なフォルダーを作成し、その中に本スク
* リプトと、HtmlAgilityPack.1.4.0.zip を解凍してできる HtmlAgilityPack.dll
* など3つのファイルを格納します。
*
*    HtmlAgilityPack.dll
*    HtmlAgilityPack.pdb
*    HtmlAgilityPack.XML
*    PracticalFS.Errata.fsx
*
* そして、「fsi PracticalFS.Errata.fsx」コマンドを実行して、同フォルダー内に
* Errata.html を生成します。
*)

#r@"HtmlAgilityPack.dll"

module Scraper =
    open System
    open HtmlAgilityPack

    let readUri (addr: Uri) =
        use webc = new System.Net.WebClient()
        let strm = webc.OpenRead(addr)
        new System.IO.StreamReader(strm)
    let loadHtml (addr: Uri) =
        let html   = HtmlDocument()
        use reader = readUri addr
        html.Load reader
        html.DocumentNode

    let selectNode xpath (node: HtmlNode) =
        node.SelectSingleNode(xpath)
    let selectNodes xpath (node: HtmlNode) =
        node.SelectNodes(xpath)

    let getHtml (node: HtmlNode) = node.InnerHtml
    let getText (node: HtmlNode) = HtmlEntity.DeEntitize(node.InnerText)

module Program =
    open System
    open System.IO
    open System.Text.RegularExpressions
    open Scraper

    let split (s:string) =
s.Split([|' '; ' '|], StringSplitOptions.RemoveEmptyEntries)
    let pageNum s =
String.Format("{0:000}", Regex.Replace(s, "[^\d]*(\d+).*", "$1") |> int)
    let correct s =
Regex.Replace(s, @"<strong>", @"<strong style=""color: #c00;"">")
    let ssget ss i =
if i < Array.length ss then ss.[i] else""
    
    let fromGihyo () =
        Uri(@"http://gihyo.jp/book/2011/978-4-7741-4516-7/support")
        |> loadHtml
        |> selectNode @"//div[@class='readingContent01']"
    let fromMsdnB () =
        Uri(@"http://blogs.msdn.com/b/shozoa/archive/2012/02/29/practical-f-errata1.aspx")
        |> loadHtml
        |> selectNode @"//div[@id='ctl00_content_ctl00_content']//div[contains(@class, 'post-content')]"
    let getRecords root =
        Seq.zip (selectNodes @"./h4"          root)
                (selectNodes @"./table/tbody" root)
        |> Seq.map (fun (h4, tb) ->
             let xs = h4 |> getText |> split
             let ys = tb |> selectNodes @"./tr/td" |> Seq.map getHtml |> Seq.toArray
             [| pageNum (ssget xs 0); ssget xs 1; ssget ys 0; correct (ssget ys 1) |])

    let writeTable (writer: StreamWriter) =
        writer.WriteLine(@"<table>")
        writer.WriteLine(@"<tr><th style=""width: 36px;"">Page</th><th style=""width: 98px;"">見出し</th><th>誤</th><th>正</th></tr>")
        let xs, ys = getRecords <| fromGihyo (),
                     getRecords <| fromMsdnB ()
        Seq.append xs ys
        |> Seq.sort
        |> Seq.iter (fun arr ->
             writer.WriteLine("<tr>" + String.concat "" (Array.map (fun s ->"<td>"+s+"</td>") arr) + "</tr>"))
        writer.WriteLine(@"</table>")

    let main () =
        let path = Path.Combine(__SOURCE_DIRECTORY__, "Errata.html")
        use writer = new StreamWriter(path)
        writer.WriteLine(@"<!DOCTYPE html>")
        writer.WriteLine(@"<html>")
        writer.WriteLine(@"<head>")
        writer.WriteLine(@"<title>実践F# 関数型プログラミング入門(正誤表)</title>")
        writer.WriteLine(@"<meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"">")
        writer.WriteLine(@"<style>")
        writer.WriteLine(@"    table { border-collapse: collapse; empty-cells:show; }")
        writer.WriteLine(@"    th, td { border: solid 2px #ccc; }")
        writer.WriteLine(@"</style>")
        writer.WriteLine(@"</head>")
        writer.WriteLine(@"<body>")
        writeTable writer
        writer.WriteLine(@"</body>")
        writer.WriteLine(@"</html>")

    do main ()

Viewing all articles
Browse latest Browse all 26

Trending Articles