Try   HackMD

歷史的刻痕轉型正義資料庫wikidata化計畫

本共筆短網址 https://tg.pe/1uA

緣起

臺灣轉型正義資料庫在近日釋出,內容涵蓋所有當時的受害者、審判者與相關的判決資料,這是第一次有完整且檢索功能相對完善的資料平台網站上線。

然而,這只是一切的開端。這個資料庫提供了一個很好的資料基礎,讓我們能透過將其導入至 Wikidata 中,進一步去做其他平台線上資料的編輯與現有維基百科資料的補充。

丁窈窕 為例,我們可以透過轉型正義資料庫去補充Wikidata中現有的資料,同時進行線上資料的檢索;將線上所有的有關資料,以參考文獻的方式添加進入 Wikidata 中。除了能夠增進 Wikidata 內的條目資料品質外,也能提供後續研究者能直接在 Wikidata 條目中,索引到大部分線上資料的頁面位置。

透過將人物建立在 Wikidata 中,可以使資料的分析更加容易。現有的臺灣轉型資料庫可能因為資料授權的問題,或是其餘的技術問題;除了資料還無法透過開放授權釋出之外,目前提供的分析資料仍為 xslx 或 ods ,彈性仍不及其他格式來得大。

以 Wikidata 目前可提供的分析,可以很精確的做到人物與人物之間的脈絡比較與爬梳,同時以 CC0 釋出的資料庫與其他的人物分析平台能有更好的授權兼容性。

最後,這個專案究竟有找人來做什麼呢?我們今天希望找人來一起蒐集資料、整理資料,同時把轉型正義資料庫中的人物,建立在 Wikidata 中。
如果,已經有條目的人物就透過轉型正義資料庫與線上資料去增補資料內容。沒有條目的人物就進行條目建立;除了以轉型正義資料庫為參考資料外,也透過線上資料的蒐集轉進 Wikidata 參考文獻中。

資料填寫重點

  • 性質 P31 -> 人類Q5

    • 必填
  • 性別 P21

    • 必填
    • 男性(Q6581097)
    • 女性(Q6581072)
    • 雙性人(Q1097630)
    • 女跨性别者(Q1052281)
    • 男跨性别者(Q2449503)
    • 如果新增的非男性或女性是其他選項,請務必添加參考來源
  • 國籍 P27

    • 必填
    • 中華民國 Q865
  • 姓氏 P734

    • 必填
  • 出生地 P19

    • 請至少新增至縣、市等級
    • 請勿寫出生於哪一國
  • 出生日期 P569

    • 西元年月日
    • 請務必新增參考文獻
  • 死亡日期 P570

    • 西元年月日
    • 請務必新增參考文獻
  • 死亡地 P20

    • 請至少新增至縣、市等級
    • 請勿寫死亡於哪一國
  • 死亡方式 P1196

    • 自然死亡
    • 意外
    • 殺害
    • 有待調查
    • 死刑
    • 未知數值
    • 非正常死亡
    • 安樂死
    • 戰死
    • 緩和鎮靜
    • 謀殺
    • 自殺
    • 請務必新增參考文獻
    • 不知道可略過
  • 死因 P509

    • 請務必新增參考文獻
    • 不知道可略過
  • 墓地

    • 實際地點
    • 不知道可略過

參考文獻

  • 載於
    • 轉型正義資料庫 Q87472037
    • 如果從資料庫轉錄的內容請一定要新增這一筆
  • 來源網址
    • 必填
  • 作品與名稱語言
    • 必填
    • 只要是中華民國境內的中文文本都是 「中華民國國語」
  • 檢索日期
    • 必填
    • 20200314
    • 依實際檢索時間填寫

資料源

任務分配

範圍以轉型正義資料庫內的籍貫地理區域分類

  • [ ]KOKUYO:死刑(請大家跳過死刑犯之編輯)
  • [ ]Allen:籍貫新北市
  • [x]Frank:籍貫澎湖縣
  • [ ]Frank:籍貫台南縣(死刑除外)
  • [ ]Jamie:籍貫台南市

討論區

歡迎大家在下面開槓

// This tool depends on "github.com/jd3main/gowd" (commit id: 74060fd)

package main

import (
	"encoding/json"
	"fmt"
	"html"
	"io/ioutil"
	"strconv"
	"strings"

	gowd "github.com/jd3main/gowd"
)

var client *gowd.Client

type SearchResults struct {
	SearchInfo interface{}
	Values     []ItemInfo `json:"search"`
}
type ItemInfo struct {
	Id          string
	Label       string
	Description string
}

func main() {
	client = &gowd.Client{
		AcceptFormat: "json",
		Languages:    []string{"zh-tw", "zh-hant", "zh"}}

	names := getNames()
	fmt.Printf("%v\n", names)

	// Search Existence
	for _, name := range names {
		res, err := searchEntity(name)
		if err != nil {
			fmt.Println(err)
			return
		}
		if len(res.Values) == 0 {
			fmt.Printf("%v: no result\n", name)
			continue
		}
		fmt.Printf("%v: %v: %v\n", name, res.Values[0].Id, res.Values[0].Label)
	}
}

func getNames() []string {
	siteURL := "https://twtjcdb.tjc.gov.tw/Search/S?C4=%E8%87%BA%E7%81%A3%E7%9C%81&CI=%E8%87%BA%E5%8D%97%E5%B8%82&O=a"
	names, err := getNamesFromPage(siteURL, 1)
	if err != nil {
		fmt.Println(err)
	}
	return names
}

func getNamesFromPage(siteURL string, page int) (names []string, err error) {
	fullURL := siteURL + "&N=" + strconv.Itoa(page)
	fmt.Printf("URL: %v\n", fullURL)
	resp, err := client.Get(fullURL)
	fmt.Printf("resp.Body = %v\n", resp.Body)
	defer resp.Body.Close()
	content, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return
	}
	doc := string(content)
	fmt.Printf("len(doc) = %v\n", len(doc))
	for {
		tagIndex := strings.Index(doc, "<a href=\"/Search/Detail")
		if tagIndex == -1 {
			break
		}
		nameBegIndex := tagIndex + strings.Index(doc[tagIndex:], ">") + 1
		nameEndIndex := nameBegIndex + strings.Index(doc[nameBegIndex:], "<")
		name := html.UnescapeString(doc[nameBegIndex:nameEndIndex])
		names = append(names, name)

		doc = doc[nameEndIndex:]
	}
	return
}

func searchEntity(name string) (res SearchResults, err error) {
	reader, _, err := client.CallMwApi(gowd.SearchEntities(name, "zh"))
	blob, _ := ioutil.ReadAll(reader)
	err = json.Unmarshal(blob, &res)
	return
}