diff --git a/catalog/book/tests.py b/catalog/book/tests.py
index fafb859f..7415dbf3 100644
--- a/catalog/book/tests.py
+++ b/catalog/book/tests.py
@@ -169,6 +169,54 @@ class GoogleBooksTestCase(TestCase):
self.assertEqual(site.resource.item.title, "1984 Nineteen Eighty-Four")
+class BooksTWTestCase(TestCase):
+ def test_parse(self):
+ t_type = IdType.BooksTW
+ t_id = "0010947886"
+ t_url = "https://www.books.com.tw/products/0010947886?loc=P_br_60nq68yhb_D_2aabdc_B_1"
+ t_url2 = "https://www.books.com.tw/products/0010947886"
+ p1 = SiteManager.get_site_by_url(t_url)
+ p2 = SiteManager.get_site_by_url(t_url2)
+ self.assertIsNotNone(p1)
+ self.assertEqual(p1.url, t_url2)
+ self.assertEqual(p1.ID_TYPE, t_type)
+ self.assertEqual(p1.id_value, t_id)
+ self.assertEqual(p2.url, t_url2)
+
+ @use_local_response
+ def test_scrape(self):
+ t_url = "https://www.books.com.tw/products/0010947886"
+ site = SiteManager.get_site_by_url(t_url)
+ self.assertIsNotNone(site)
+ self.assertEqual(site.ready, False)
+ site.get_resource_ready()
+ self.assertEqual(site.ready, True)
+ self.assertEqual(
+ site.resource.metadata.get("title"),
+ "阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興",
+ )
+ self.assertEqual(
+ site.resource.metadata.get("orig_title"),
+ "Arabs: A 3000-Year History of Peoples, Tribes and Empires",
+ )
+ self.assertEqual(site.resource.metadata.get("isbn"), "9786263152236")
+ self.assertEqual(site.resource.metadata.get("author"), ["Tim Mackintosh-Smith"])
+ self.assertEqual(site.resource.metadata.get("translator"), ["吳莉君"])
+ self.assertEqual(site.resource.metadata.get("language"), "繁體中文")
+ self.assertEqual(site.resource.metadata.get("pub_house"), "臉譜")
+ self.assertEqual(site.resource.metadata.get("pub_year"), 2023)
+ self.assertEqual(site.resource.metadata.get("pub_month"), 2)
+ self.assertEqual(site.resource.metadata.get("binding"), "平裝")
+ self.assertEqual(site.resource.metadata.get("pages"), 792)
+ self.assertEqual(site.resource.metadata.get("price"), "1050 NTD")
+ self.assertEqual(site.resource.id_type, IdType.BooksTW)
+ self.assertEqual(site.resource.id_value, "0010947886")
+ self.assertEqual(site.resource.item.isbn, "9786263152236")
+ self.assertEqual(
+ site.resource.item.title, "阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興"
+ )
+
+
class DoubanBookTestCase(TestCase):
def setUp(self):
pass
diff --git a/catalog/common/models.py b/catalog/common/models.py
index 201b0509..acb804b0 100644
--- a/catalog/common/models.py
+++ b/catalog/common/models.py
@@ -25,6 +25,7 @@ class SiteName(models.TextChoices):
Douban = "douban", _("豆瓣")
Goodreads = "goodreads", _("Goodreads")
GoogleBooks = "googlebooks", _("谷歌图书")
+ BooksTW = "bookstw", _("博客来")
IMDB = "imdb", _("IMDB")
TMDB = "tmdb", _("The Movie Database")
Bandcamp = "bandcamp", _("Bandcamp")
@@ -61,6 +62,7 @@ class IdType(models.TextChoices):
DoubanMusic = "doubanmusic", _("豆瓣音乐")
DoubanGame = "doubangame", _("豆瓣游戏")
DoubanDrama = "doubandrama", _("豆瓣舞台剧")
+ BooksTW = "bookstw", _("博客来图书")
Bandcamp = "bandcamp", _("Bandcamp")
Spotify_Album = "spotify_album", _("Spotify专辑")
Spotify_Show = "spotify_show", _("Spotify播客")
diff --git a/catalog/migrations/0005_bookstw.py b/catalog/migrations/0005_bookstw.py
new file mode 100644
index 00000000..d3abd6fa
--- /dev/null
+++ b/catalog/migrations/0005_bookstw.py
@@ -0,0 +1,111 @@
+# Generated by Django 3.2.18 on 2023-04-25 23:02
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+ dependencies = [
+ ("catalog", "0004_podcast_no_real_change"),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name="externalresource",
+ name="id_type",
+ field=models.CharField(
+ choices=[
+ ("wikidata", "维基数据"),
+ ("isbn10", "ISBN10"),
+ ("isbn", "ISBN"),
+ ("asin", "ASIN"),
+ ("issn", "ISSN"),
+ ("cubn", "统一书号"),
+ ("isrc", "ISRC"),
+ ("gtin", "GTIN UPC EAN码"),
+ ("rss", "RSS Feed URL"),
+ ("imdb", "IMDb"),
+ ("tmdb_tv", "TMDB剧集"),
+ ("tmdb_tvseason", "TMDB剧集"),
+ ("tmdb_tvepisode", "TMDB剧集"),
+ ("tmdb_movie", "TMDB电影"),
+ ("goodreads", "Goodreads"),
+ ("goodreads_work", "Goodreads著作"),
+ ("googlebooks", "谷歌图书"),
+ ("doubanbook", "豆瓣读书"),
+ ("doubanbook_work", "豆瓣读书著作"),
+ ("doubanmovie", "豆瓣电影"),
+ ("doubanmusic", "豆瓣音乐"),
+ ("doubangame", "豆瓣游戏"),
+ ("doubandrama", "豆瓣舞台剧"),
+ ("bookstw", "博客来图书"),
+ ("bandcamp", "Bandcamp"),
+ ("spotify_album", "Spotify专辑"),
+ ("spotify_show", "Spotify播客"),
+ ("discogs_release", "Discogs Release"),
+ ("discogs_master", "Discogs Master"),
+ ("musicbrainz", "MusicBrainz ID"),
+ ("doubanbook_author", "豆瓣读书作者"),
+ ("doubanmovie_celebrity", "豆瓣电影影人"),
+ ("goodreads_author", "Goodreads作者"),
+ ("spotify_artist", "Spotify艺术家"),
+ ("tmdb_person", "TMDB影人"),
+ ("igdb", "IGDB游戏"),
+ ("steam", "Steam游戏"),
+ ("bangumi", "Bangumi"),
+ ("apple_podcast", "苹果播客"),
+ ],
+ max_length=50,
+ verbose_name="IdType of the source site",
+ ),
+ ),
+ migrations.AlterField(
+ model_name="itemlookupid",
+ name="id_type",
+ field=models.CharField(
+ blank=True,
+ choices=[
+ ("wikidata", "维基数据"),
+ ("isbn10", "ISBN10"),
+ ("isbn", "ISBN"),
+ ("asin", "ASIN"),
+ ("issn", "ISSN"),
+ ("cubn", "统一书号"),
+ ("isrc", "ISRC"),
+ ("gtin", "GTIN UPC EAN码"),
+ ("rss", "RSS Feed URL"),
+ ("imdb", "IMDb"),
+ ("tmdb_tv", "TMDB剧集"),
+ ("tmdb_tvseason", "TMDB剧集"),
+ ("tmdb_tvepisode", "TMDB剧集"),
+ ("tmdb_movie", "TMDB电影"),
+ ("goodreads", "Goodreads"),
+ ("goodreads_work", "Goodreads著作"),
+ ("googlebooks", "谷歌图书"),
+ ("doubanbook", "豆瓣读书"),
+ ("doubanbook_work", "豆瓣读书著作"),
+ ("doubanmovie", "豆瓣电影"),
+ ("doubanmusic", "豆瓣音乐"),
+ ("doubangame", "豆瓣游戏"),
+ ("doubandrama", "豆瓣舞台剧"),
+ ("bookstw", "博客来图书"),
+ ("bandcamp", "Bandcamp"),
+ ("spotify_album", "Spotify专辑"),
+ ("spotify_show", "Spotify播客"),
+ ("discogs_release", "Discogs Release"),
+ ("discogs_master", "Discogs Master"),
+ ("musicbrainz", "MusicBrainz ID"),
+ ("doubanbook_author", "豆瓣读书作者"),
+ ("doubanmovie_celebrity", "豆瓣电影影人"),
+ ("goodreads_author", "Goodreads作者"),
+ ("spotify_artist", "Spotify艺术家"),
+ ("tmdb_person", "TMDB影人"),
+ ("igdb", "IGDB游戏"),
+ ("steam", "Steam游戏"),
+ ("bangumi", "Bangumi"),
+ ("apple_podcast", "苹果播客"),
+ ],
+ max_length=50,
+ verbose_name="源网站",
+ ),
+ ),
+ ]
diff --git a/catalog/sites/__init__.py b/catalog/sites/__init__.py
index 4d995206..d073cce7 100644
--- a/catalog/sites/__init__.py
+++ b/catalog/sites/__init__.py
@@ -18,3 +18,4 @@ from .bandcamp import Bandcamp
from .bangumi import Bangumi
from .discogs import DiscogsRelease
from .discogs import DiscogsMaster
+from .bookstw import BooksTW
diff --git a/catalog/sites/bookstw.py b/catalog/sites/bookstw.py
new file mode 100644
index 00000000..6082c0f9
--- /dev/null
+++ b/catalog/sites/bookstw.py
@@ -0,0 +1,137 @@
+from catalog.common import *
+from catalog.book.models import *
+from catalog.book.utils import *
+from .douban import *
+import logging
+
+
+_logger = logging.getLogger(__name__)
+
+
+@SiteManager.register
+class BooksTW(AbstractSite):
+ SITE_NAME = SiteName.BooksTW
+ ID_TYPE = IdType.BooksTW
+ URL_PATTERNS = [
+ r"\w+://www\.books\.com\.tw/products/(\w+)",
+ ]
+ WIKI_PROPERTY_ID = "?"
+ DEFAULT_MODEL = Edition
+
+ @classmethod
+ def id_to_url(cls, id_value):
+ return "https://www.books.com.tw/products/" + id_value
+
+ def scrape(self):
+ content = BasicDownloader(self.url).download().html()
+
+ isbn_elem = content.xpath(
+ "//div[@class='bd']/ul/li[starts-with(text(),'ISBN:')]/text()"
+ )
+ isbn = isbn_elem[0].strip().split(":", 1)[1].strip() if isbn_elem else None
+
+ # isbn_elem = content.xpath(
+ # "//div[@class='bd']/ul/li[starts-with(text(),'EISBN')]/text()"
+ # )
+ # eisbn = isbn_elem[0].strip().split(":", 1)[1].strip() if isbn_elem else None
+
+ title = content.xpath("string(//h1)") or f"Unknown Title {self.id_value}"
+ subtitle = None
+ orig_title = content.xpath("string(//h1/following-sibling::h2)")
+
+ authors = content.xpath("string(//div/ul/li[contains(text(),'作者:')])")
+ authors = authors.strip().split(":", 1)[1].split(",") if authors else []
+ authors = [s.strip() for s in authors]
+ # author_orig = content.xpath("string(//div/ul/li[contains(text(),'原文作者:')])")
+
+ translators = content.xpath("string(//div/ul/li[contains(text(),'譯者:')])")
+ translators = (
+ translators.strip().split(":", 1)[1].split(",") if translators else []
+ )
+ translators = [s.strip() for s in translators]
+
+ language_elem = content.xpath("//div/ul/li[starts-with(text(),'語言:')]/text()")
+ language = (
+ language_elem[0].strip().split(":")[1].strip() if language_elem else None
+ )
+
+ pub_house = content.xpath("string(//div/ul/li[contains(text(),'出版社:')])")
+ pub_house = (
+ pub_house.strip().split(":", 1)[1].strip().split(" ", 1)[0]
+ if pub_house
+ else None
+ )
+
+ pub_date = content.xpath("string(//div/ul/li[contains(text(),'出版日期:')])")
+ pub_date = re.match(
+ r"(\d+)/(\d+)/(\d+)\s*$",
+ pub_date.strip().split(":", 1)[1].strip().split(" ", 1)[0]
+ if pub_date
+ else "",
+ )
+ if pub_date:
+ pub_year = int(pub_date[1])
+ pub_month = int(pub_date[2])
+ else:
+ pub_year = None
+ pub_month = None
+
+ spec = content.xpath("string(//div/ul/li[contains(text(),'規格:')])")
+ spec = spec.strip().split(":", 1)[1].strip().split("/") if spec else []
+ if len(spec) > 1:
+ binding = spec[0].strip()
+ pages = spec[1].strip().split("頁")
+ pages = int(pages[0]) if len(pages) > 1 else None
+ if pages and (pages > 999999 or pages < 1):
+ pages = None
+ else:
+ binding = None
+ pages = None
+
+ price = content.xpath("string(//div/ul/li[contains(text(),'定價:')])")
+ price = (
+ price.strip().split(":", 1)[1].split("元")[0].strip() + " NTD"
+ if price
+ else None
+ )
+
+ brief = content.xpath("string(//h3[text()='內容簡介']/following-sibling::div)")
+ contents = content.xpath("string(//h3[text()='目錄']/following-sibling::div)")
+
+ series = None
+ imprint = None
+
+ img_url = content.xpath(
+ "string(//div[contains(@class,'cover_img')]//img[contains(@class,'cover')]/@src)"
+ )
+ img_url = re.sub(r"&[wh]=\d+", "", img_url) if img_url else None
+
+ data = {
+ "title": title,
+ "subtitle": subtitle,
+ "orig_title": orig_title,
+ "author": authors,
+ "translator": translators,
+ "language": language,
+ "pub_house": pub_house,
+ "pub_year": pub_year,
+ "pub_month": pub_month,
+ "binding": binding,
+ "price": price,
+ "pages": pages,
+ "isbn": isbn,
+ "brief": brief,
+ "contents": contents,
+ "series": series,
+ "imprint": imprint,
+ "cover_image_url": img_url,
+ }
+
+ pd = ResourceContent(metadata=data)
+ t, n = detect_isbn_asin(isbn)
+ if t:
+ pd.lookup_ids[t] = n
+ pd.cover_image, pd.cover_image_extention = BasicImageDownloader.download_image(
+ img_url, self.url
+ )
+ return pd
diff --git a/catalog/sites/rss.py b/catalog/sites/rss.py
index 73428999..1dbb97c1 100644
--- a/catalog/sites/rss.py
+++ b/catalog/sites/rss.py
@@ -47,7 +47,7 @@ class RSS(AbstractSite):
@classmethod
def validate_url_fallback(cls, url):
- val = URLValidator(verify_exists=False)
+ val = URLValidator()
try:
val(url)
return cls.parse_feed_from_url(url) is not None
diff --git a/common/static/sass/_Label.sass b/common/static/sass/_Label.sass
index 984d38a5..06b40a3d 100644
--- a/common/static/sass/_Label.sass
+++ b/common/static/sass/_Label.sass
@@ -15,6 +15,8 @@ $bangumi-color-primary: #F09199
$bangumi-color-secondary: #FCFCFC
$goodreads-color-primary: #372213
$goodreads-color-secondary: #F4F1EA
+$bookstw-color-primary: white
+$bookstw-color-secondary: #7FBA19
$tmdb-color-primary: #91CCA3
$tmdb-color-secondary: #1FB4E2
$bandcamp-color-primary: #28A0C1
@@ -78,6 +80,10 @@ $bandcamp-color-secondary: white
background: $goodreads-color-secondary
color: $goodreads-color-primary
font-weight: lighter
+ &.source-label__bookstw
+ background: $bookstw-color-secondary
+ color: $bookstw-color-primary
+ font-weight: lighter
&.source-label__tmdb
background: linear-gradient(90deg, $tmdb-color-primary, $tmdb-color-secondary)
color: white
diff --git a/doc/catalog.md b/doc/catalog.md
index bf7fa6cc..b926af22 100644
--- a/doc/catalog.md
+++ b/doc/catalog.md
@@ -88,14 +88,14 @@ classDiagram
Add a new site
--------------
- - add a new item to `IdType` enum in `catalog/common/models.py`
+ - add a new value to `IdType` and `SiteName` in `catalog/common/models.py`
- add a new file in `catalog/sites/`, a new class inherits `AbstractSite`, with:
* `SITE_NAME`
* `ID_TYPE`
* `URL_PATTERNS`
* `WIKI_PROPERTY_ID` (not used now)
* `DEFAULT_MODEL` (unless specified in `scrape()` return val)
- * a `classmethod` `id_to_url()`
+ * a classmethod `id_to_url()`
* a method `scrape()` returns a `ResourceContent` object
* ...
diff --git a/test_data/https___www_books_com_tw_products_0010947886 b/test_data/https___www_books_com_tw_products_0010947886
new file mode 100644
index 00000000..c7930d65
--- /dev/null
+++ b/test_data/https___www_books_com_tw_products_0010947886
@@ -0,0 +1,1077 @@
+
+
+
+
+
+博客來-阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
![]()
+

+
+
+
+
+
+
阿拉伯人三千年:從民族、部落、語言、文化、宗教到帝國,綜覽阿拉伯世界的崛起、衰落與再興
+
+
+
+
+
+
+
+
+- 定價:1050元
+- 優惠價:79折829元
- 優惠期限:2023年06月30日止
+
+
+
+
+
- 可配送點:台灣、蘭嶼、綠島、澎湖、金門、馬祖
- 可取貨點:台灣、蘭嶼、綠島、澎湖、金門、馬祖
- 台北、新北、基隆宅配快速到貨(除外地區)
+
- 可配送點:全球
- 可取貨點:香港、澳門、新加坡、馬來西亞、菲律賓
+
+
+
+載入中...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
內容簡介
+
+
+
貫串一個傑出民族、文明和語言的宏大歷史,
+將一千五百年前的沙漠詩歌與今日的國際情勢、戰爭創傷相互串聯──
+著名阿拉伯語學者、當代旅行文學名家,旅居阿拉伯世界近40年,提姆•麥金塔―史密斯傾力巨著,
+跨越三千年、三大洲,理解中東與阿拉伯世界必讀之作!
+
+
+
◆國立政治大學阿拉伯語文學系退休教授鄭慧慈老師專業審定•專文導讀
+◆《週日泰晤士報》、《泰晤士報文學增刊》年度選書
+◆亞馬遜書店編輯精選「最佳歷史選書」
+◆《耶路撒冷三千年》(Jerusalem)作者盛讚
+
+
┤口碑推薦├
+
奇慈飛 「蹲點阿拉伯」部落客
+
阿 潑 轉角國際專欄作者
+
柯睿信 「歷史說書人History Storyteller」主編
+
莊德仁 臺北市立建國高中歷史科教師、國立臺灣師範大學歷史所博士
+
張育軒 「說說伊朗」創辦人
+
黃春木 臺北市立建國高中歷史科教師
+
蔡依橙 「陪你看國際新聞」創辦人
+
謝金魚 歷史作家
+
+
🐫一場深入阿拉伯的靈魂與中東族群記憶的壯闊之旅,
+帶領讀者踏入滾滾黃沙、游牧營帳、駱駝商隊與伊斯蘭拜禱聲的世界,揭開阿拉伯歷史的面紗。
+
+一千一百多年前,傑出的早期阿拉伯歷史學家馬蘇第,把講述阿拉伯故事這項任務,比喻成「有人發現一大堆散落的寶石,
+有各種不同的款式和顏色,然後得想辦法按照秩序將它們串接起來,變成一條珍貴項鍊」。
+
+《阿拉伯人三千年》接下了這項任務。在本書中,作家暨知名學者提姆•麥金塔─史密斯以細節豐富、
+流暢優美的文字,搭配他別具一格的說故事方式,將阿拉伯民族與部落在廣袤世界開疆拓土、
+傳播文化的過程依年代串接起來,讓我們看到語言之線如何貫穿了阿拉伯的歷史與認同。
+從最早期沙漠岩石上的塗鴉,到晚近往往相當血腥的壓制異聲──他聆聽阿拉伯人數千年來的聲音,也聆聽他們「口若懸河的沉默」。
+
+本書中年代最早上溯至西元前九世紀,涵蓋了伊斯蘭出現之前與之後,各一千四百年留有紀錄的歷史時期。
+在伊斯蘭之前,文學與文化大多是口語的。當第一本阿拉伯文書籍《古蘭經》問世以後,它在一個重要的歷史時刻快速團結了阿拉伯人。
+然而不到三百年,大一統的阿拉伯就成了只能追憶的珍貴往事。接下來的一千年,除了兩次例外,阿拉伯人都處於四分五裂的狀態,
+先後受到土耳其人、波斯人、柏柏人和歐洲人的統治。近期發生的「阿拉伯之春」和隨後的混亂餘波再次顯示,話語──標語和宣傳、
+喑啞的真相與喧鬧的謊言──仍然在形塑著阿拉伯世界;兼具創造與毀滅力量的歷史「火輪」依舊滾動不止,直至今日……
+
+這部宏觀的著作涵蓋了近三千年的阿拉伯歷史,藉由追溯阿拉伯語言的起源細說從頭,
+再探討到這種語言如何形塑擴散於三大洲的宗教、文化與人民樣貌。讀者可破除長年的迷思與誤解,
+更加理解世界發展的全貌。本書不僅是一本扎實的歷史作品,更是一趟跨越時空的紙上旅程。
+
+◎章節概要
+
+導言 凝聚話語
+作者認為阿拉伯族群最具代表性的共通點:語言。「在三千年有文字紀錄的阿拉伯歷史裡,所集之言啟發了三波團結的浪潮」:第一波浪潮既古老又緩慢但深入,是一種種族的自我意識;第二波是一個實體擴張的海嘯;最後以漫長的低潮作收,但留下豐富、持久的語言沉積。
+
+第一章 來自荒野的聲音
+先從地理上的阿拉伯地區談起,比較阿拉伯半島與歐亞大陸上另外兩塊次大陸在地緣上的異同,再概論阿拉伯半島的地形和氣候對於早期人類遷徙和歷史的影響。論述阿拉伯半島和中東兩大沃土最早的民族亞述人和聖經中最早對於「阿拉伯人」的描述,以及這些民族懂得駕馭駱駝之後的機動能力。
+
+第二章 民族與部落
+論述伊斯蘭教興起前阿拉伯半島靠海南部(定居者)與沙漠內陸北部(游牧者)民族之間的互動。「阿拉伯歷史」不應只視為從伊斯蘭教興起之後才開始,甚至不應該只視為「阿拉伯人的歷史」。各地的方言和語言流動,促成阿拉伯語詩歌的興起與發展,將這個地區的各個民族融合為一個文化上的國族。
+
+第三章 風流雲散
+以文法的主動與被動為譬喻,描述阿拉伯人在定居和行動時的差異。早期伊斯蘭的口述故事說明新興的伊斯蘭教源自既有、古老的阿拉伯人背景,這個背景除了涵蓋穆罕默德在麥加附近的地域外,也包括南方定居者的環境。這代表阿拉伯半島南方的民族納進阿拉伯民族,原本多元的民族已經被伊斯蘭教統一。
+
+第四章 在偉大的邊緣
+西元六世紀,波斯人與阿拉伯人的分野漸漸明朗。部落之間在戰爭前是詩人的語言交戰,戰爭後又由詩人歌頌勝利。言語的力量之大,促成阿拉伯人透過詩詞成為一體:古蘭經中稱穆罕默德為「阿拉伯人」,因為他屬於一個由語言一統的文化。這些詩詞是我們一窺伊斯蘭教興起之前阿拉伯文化的最佳管道。
+
+第五章 啟示與革命
+以先知穆罕默德化解部落糾紛,將黑石(Black Stone)放入克爾白(Ka’bah)的故事說起,說明伊斯蘭教的習俗可追溯至伊斯蘭教以前的歷史。古蘭經是直接從穆罕默德的啟示抄寫下來的,代表的不僅是既有的古老神聖語言,也是一個實體的新經文。
+
+第六章 上帝與凱撒
+穆罕默德打破麥加人傳統的宗教、習俗和社會架構,成為阿拉伯人共主,並利用書寫的文本這種「媒體」吸引了阿拉伯各地的酋長。他們前來不一定是「皈依」宗教,而是忠於這個新興的勢力:islam一字是「臣服」之意,一個人有可能是muslim「臣服者」,但不是mu’min「相信者」。
+
+第七章 彎月軍
+阿拉伯人一向無法一統,穆罕默德死後紛爭又起。新的阿拉伯取代了舊的阿拉伯,但即使「彎月軍」(作者依十字軍和日後象徵伊斯蘭的彎月自創的字)橫掃,可看出他們要的不是用宗教同化其他民族,而是要抽稅。阿拉伯人和被征服的波斯人通婚,造成波斯人的「東方」語言和風俗滲透進阿拉伯文化。
+
+第八章 大馬士革王國
+烏瑪亞家族(Umayyad)原為伊斯蘭教前的麥加望族,遷徙至大馬士革後成為新的阿拉伯人共主,將原本不說阿拉伯語的阿拉伯半島南部部落完整納入整個阿拉伯民族的系譜。但烏瑪亞家族奪權後,南方以麥加為中心仍然不斷有勢力效忠於已故的阿里,這便是日後什葉教派與遜尼教派分裂的起源。
+
+第九章 巴格達帝國
+阿拔斯統治者清除政敵後興建巴格達,將這個首都打造成多元的國際大城,波斯人從祅教改信伊斯蘭教。哈里發推廣科學研究及古蘭經的研究和定型,「書寫的阿拉伯文因此是建構出來的,語言學家在合成這種泛阿拉伯的語言時,更強化了各種多元的部落和民族同屬一個種族的概念」。
+
+第十章 反正統文化,反正統哈里發
+以阿拉伯人的觀點來看,土耳其人的面貌幾乎是阿拉伯人的相反,但在哈里發帝國的統治下,本來只是受奴役的土耳其人被擾動、被帶到權力核心,最後更取代阿拉伯人的統治。十世紀以降,帝國各地不時出現地方領袖占地為王又迅速落敗,倖存者在伊比利半島和北非建立了哈里發政權。
+
+第十一章 瓶中精靈
+從十字軍東征開始,殘餘的阿拉伯帝國腹背受敵。十三世紀,阿拉伯世界面臨兩大災難,西邊有十字軍攻下埃及重要港口,東邊則是成吉思汗的軍隊進逼波斯。土耳其人抵擋蒙古大軍的攻勢,讓伊斯蘭文明得以在埃及和敘利亞保存,但黑死病又成為十四世紀另一波襲來的惡運。
+
+第十二章 季風大亨
+阿拉伯人向外遷徙時,伊斯蘭教也在各地有了不同的面貌。鄂圖曼土耳其人興起,雖然與阿拉伯人同有伊斯蘭教,用同樣的書寫系統,但鄂圖曼人一直是外人、他者,阿拉伯人則往往不再視自己為「阿拉伯人」,而是穆斯林、基督徒或猶太教徒,不再有強大的泛阿拉伯人意識,唯有阿拉伯語讓他們互相連結。
+
+第十三章 認同的再發現
+十九世紀,阿拉伯人又卡在兩大不同的強權勢力之間,一邊是正漸漸崩解的鄂圖曼土耳其帝國,另一邊是正要滲透進來的歐洲殖民勢力。此時一統的力量不是伊斯蘭教,而是「國族主義」,核心的概念是「統一的阿拉伯民族國家」。一次大戰以降,阿拉伯民族主義面臨分裂,西方眼中的中東變得混沌不明。
+
+第十四章 希望的年代
+二次大戰後,阿拉伯團結的思潮在殖民主義和猶太復國主義之下陷入低潮。1952年的埃及革命後,軍官納瑟獨攬大權,繼而成為延續阿拉伯人古老雄辯傳統的現代繼承人。日後,阿拉伯聯合共和國、阿拉伯合眾國形成又解體。產石油的阿拉伯國家在與以色列交戰中獲得財富,同時洞見彼此之間的巨大差異。
+
+
第十五章 失望的年代
+二十世紀中葉,阿拉伯世界似乎處處充滿希望,但新的一波獨裁者和伊斯蘭教統治者將民主化和現代化的潮流逆轉。政治伊斯蘭被來自外國的壓力推動,世俗化的泛阿拉伯主義失敗。二十一世紀,阿拉伯國家的人民多數認為自己身為穆斯林比身為阿拉伯人更重要。思潮的倒退也讓阿拉伯人回復以前游牧部落的掠奪型態,使得阿拉伯人彼此之間互相爭戰。
+
+
+▌口碑好評
+
+本書對阿拉伯人的歷史歸納之完整實在令人讚嘆,書寫內容既無略古詳今地忘卻阿拉伯歷史上較少人知曉的前伊斯蘭時期,
+同時在影響當代世界格局甚大的近代章節中亦有深刻著墨。而書中隨處可見的阿拉伯原文詩作,更是使人在此精心構築的歷史之旅中有種身歷其境的奇妙感受。
+——
柯睿信/「歷史說書人History Storyteller」主編
+
+二〇二二年底隨著世足賽開打,阿拉伯世界又再成為一個值得探究的議題。《阿拉伯人三千年》的中文版發行正符應此時的需求。
+歷史學強調脈絡化的理解,希望能同理神入當事人的處境與感受,然理解「阿拉伯」卻因為語言的隔閡成為一大障礙。
+再者,認識阿拉伯常從伊斯蘭教的角度入手,但當伊斯蘭帝國的興起與分裂之後,國家成為關注的焦點,
+遺憾的是,「阿拉伯」卻隱沒了。以上這些都是非「阿拉伯」人同理神入「阿拉伯」世界的阻礙,也正是本書作者想要移除的努力所在。
+——
莊德仁/臺北市立建國高中歷史科教師、國立臺灣師範大學歷史所博士
+
+這不是一本歷史書,而是一本剖析阿拉伯人民族靈魂與記憶的精采作品。深入、細膩、有條有理卻又大膽充滿詩意,
+唯有作者數十年沉浸在阿拉伯文化與對其的熱愛,加上罕見的觀察力與理解,才能帶給我們這趟絕妙的閱讀旅程,
+如同在沙漠中穿過一個又一個歷史遺跡,細碎交錯的文化細節巧妙地流動在每個章節中。
+讀這本書不只是讀阿拉伯人,而是一場宏大深入的心靈探索之旅。
+——
張育軒/「說說伊朗」創辦人
+
+精湛且精采。本書是優美的書面敘事和敏銳的分析,既鮮活又原創,充滿迷人的角色和想法,
+對伊斯蘭前後的著墨同樣深刻,不僅對阿拉伯的歷史和信仰、對它的語言和文化也都流露真情。
+這本書只能出自一位對阿拉伯靈魂地理學與阿拉伯土地地理學瞭若指掌之人。
+
──賽門•蒙提費歐里(Simon Sebag Montefiore),《耶路撒冷三千年》(Jerusalem)作者
+
+麥金塔-史密斯是一位非凡的海外英國人:如他所言,一位住在土地上而非圖書館裡的作家,在現場體驗歷史。
+他以令人眩目的措辭和啟發人心的比較傳達出深厚的學識與透徹的洞見……他天賦異稟,可用引人入勝的細節和生動有力的比較來豐富整體圖像。
+
──伊恩•布萊克(Ian Black),《觀察家報》(The Observer)
+
+本書是一趟精緻愉悅的旅程,帶你穿越一個傑出民族、文明和語言的歷史。它將一千五百年前的沙漠詩歌與今日山區的戰爭創傷串聯起來。
+
──強納森•布朗(Jonathan A. C. Brown),喬治城大學阿瓦里德•本•塔拉勒伊斯蘭文明講席教授(Alwaleed bin Talal Chair of Islamic Civilization at Georgetown University)
+
+精采絕倫。這本書和其他作品的真正差別在於,它對阿拉伯歷史的洞見多不勝數,而且引人入勝。
+裡頭也有一種酸楚之情,因為在他書寫阿拉伯人的複雜故事的同時,他就置身在遭到封鎖的沙那現場,親眼目睹了葉門的內戰上演。
+
──史蒂芬•卡頓(Steven C. Caton),哈佛大學當代阿拉伯研究教授
+
+相當精采。本書寫得很好,帶有個人感觸,一個近三十年來在阿拉伯歷史最核心處親身體驗之人。
+對這本啟發人心之書我滿懷推崇,佩服它對阿拉伯歷史認同的原創性和即時性看法,迫不及待想看它上架。
+
──菲利浦•肯尼迪(Philip Kennedy),《阿拉伯文敘事傳統之肯認》(Recognition in the Arabic Narrative Tradition)作者
+
+〔麥金塔-史密斯〕處於理想的位置,將糾結的過去生動地呈現出來……〔他〕泰然自若地處理他的複雜敘事。
+
──艾瑞克•奧姆斯比(Eric Ormsby),《華爾街日報》(Wall Street Journal)
+
+麥金塔─史密斯這本爭議性的新作,去除掉數百年來錯誤的神話打造,讓阿拉伯民族動盪的歷史重新回歸到語言的堅固盤石上。
+凡是想要了解以及書寫中東地區的人,都必須閱讀並吸取這本深刻、機智的學術成就。
+
──巴納比•羅傑森(Barnaby Rogerson),《最後的十字軍》(The Last Crusaders)作者
+
+這本書旨在帶領我們踏上一條比哈里發歷史更有野心的旅程。它提出阿拉伯認同與國族性的關鍵問題。
+很難找到比麥金塔-史密斯更棒的導遊,他在西方中東觀察家的圈子裡享有近乎神話的地位。
+他在舊沙那生活了好幾十年,可怕的葉門戰爭期間也一直住在該地。在一絲不苟的學術研究中間,穿插了他從窗外街道上瞧見的軍事演習與宣傳。
+
──理查•史賓賽(Richard Spencer),《泰晤士報》(The Times)
+
+在這段浩瀚漫長、高潮迭起的歷史過程中,麥金塔-史密斯精準地挑選他的細節和分析,提供了令人敬佩的完整圖像,
+描繪出世界歷史與文化中始終遭受誤解的一部分……一趟奇妙的旅程,充滿冒險與詩歌,由一位富有同情心的敏銳觀察家講述。
+
──《科克斯書評》(Kirkus Reviews)星級評價
+
+這本精采迷人的歷史書將改變我們對阿拉伯世界的事件分析。
+
──《華盛頓書評》(Washington Book Review)
+
+
+
+
作者介紹
+
+
+作者簡介
提姆•麥金塔―史密斯Tim Mackintosh-Smith
英國阿拉伯語學者和譯者,阿拉伯文學文庫(Library of Arabic Literature)資深學者,英國《每日電訊報》譽為「沙那的智者」。著有多本關於中東的得獎著作,包括《與丹吉爾人同行--追尋中世紀旅行家伊本.巴圖塔的足跡》、《葉門:字典國度的奇幻之旅》。現居葉門,至今已旅居阿拉伯世界近四十年。
譯者簡介
吳莉君
國立臺灣師範大學歷史系畢業,譯有《觀看的方式》、《我們在此相遇》、《霍布斯邦看21世紀:全球化,民主與恐怖主義》、《建築的法則》、《雨》等書。任職出版社多年,現為自由工作者。
+
+
+
+
目錄
+
+
+ 導讀 他們與我們之間
+前言 輪與沙漏
+導言 凝聚話語
+
+【第一部 嶄露:西元前900年~西元後600年】
+第一章 來自荒野的聲音:最早期的阿拉伯人
+第二章 民族與部落:示巴人、納巴泰人和游牧民
+第三章 風流雲散:變化中的歷史文法
+第四章 在偉大的邊緣:阿拉伯人的大時代
+
+【第二部 革命:600~630年】
+第五章 啟示與革命:穆罕默德與《古蘭經》
+第六章 上帝與凱撒:麥地那國
+
+【第三部 稱霸:630~900年】
+第七章 彎月軍:開疆拓土
+第八章 大馬士革王國:烏瑪亞統治
+第九章 巴格達帝國:阿拔斯王朝
+
+【第四部 衰落:900~1350年】
+第十章 反正統文化,反正統哈里發:帝國崩解
+第十一章 瓶中精靈:蒙古人逼近
+
+【第五部 黯蝕:1350~1800年】
+第十二章 季風大亨:環印度洋地區的阿拉伯人
+
+【第六部 再興:1800年~現今】
+第十三章 認同的再發現:覺醒運動
+第十四章 希望的年代:納瑟主義、復興主義、解放、石油
+第十五章 失望的年代:獨裁者、伊斯蘭主義者、無政府君王
+
+後記 在歷史的車站
+年表
+
+
+
+
+
詳細資料
+
+
- ISBN:9786263152236
- 叢書系列:臉譜書房
- 規格:平裝 / 792頁 / 22 x 17 x 3 cm / 普通級 / 單色印刷
- 出版地:台灣
- 適讀年齡:0歲~99歲
+
+
+
+
內容連載
+
+
+在源頭處是詩人
在阿拉伯有紀錄以來的三千年歷史裡,凝聚的話語啟動過三波統一浪潮。再次借用伊本.赫勒敦的術語,ʿaṣabīyah「團體主義」總是從al-ʿarabīyah「卓越的高級阿拉伯語」那裡得到它的動力。然而,這幾波浪潮的規模,遠比伊本.赫勒敦談論的部落或王朝大多了。第一波浪潮—古遠、緩慢,但深沉,屬於族裔的自我意識,湧漲的時間在伊斯蘭出現之前一千年。第二波是一次實體擴張的海嘯,也就是阿拉伯人在七、八世紀的征服及其餘波,它消落的速度和暴起時一樣快,最後是在長期的麻痺中結束,但留下豐沃且持久的語言沉積物。第三波是由十九世紀歐洲國族主義運動所喚醒的蟄伏力量所驅動,重新發現那個族裔的、文化的—以及,到了晚近,狂熱崇拜的—自我。最後這波至今仍在肆虐。這三波浪潮將這本書的大部分章節區分成三組:每組包含的年代不一,但篇幅大致相同:「嶄露」與「革命」(西元前九○○年到西元後六三○年);「稱霸」與「衰落」(六三○到一三五○年);「黯蝕」與「再興」(一三五○年至今)。
第一波自我意識的開端相當模糊,很難標定時間。它的興起似乎是由於將駱駝馴化成馱獸,讓移動性日益提升,以及阿拉伯人開始從事長距離的運輸和貿易工作,在這種情況下,必須要有一種語言讓北阿拉伯地區使用不同方言的人可以相互理解(南阿拉伯說的是另一組語言,和北方語有遠親關係,但北方人聽不懂;兩者的距離約莫相當於德文和義大利文)。後來,在大約西元五世紀前的某個時刻,大概在半島中部的某個地方,統一的北方語的「高級」形式也有了雛形。這所謂的al-ʿarabīyah,並非日常用語,而是一種「奧祕之語」(mystical tongue),是用來「傳達神諭和背誦詩歌」。能夠掌握這種特殊用語的人—最重要的是shāʿir,這個字後來演變成「詩人」,但最古老的意思大概比較類似預言家或薩滿—就能吸引追隨者。在劫掠襲擊的時刻,shāʿir也扮演惠特曼(Whitman)筆下的詩人角色,是「戰爭最致命的力量……能用他說出的每句話汲出鮮血。」
+
+
+
+
+
相關活動
+
+
+
+
+
+
購物說明
+
+
若您具有法人身份為常態性且大量購書者,或有特殊作業需求,建議您可洽詢「企業採購」。
+
+退換貨說明
+
+會員所購買的商品均享有到貨十天的猶豫期(含例假日)。退回之商品必須於猶豫期內寄回。
+
+辦理退換貨時,商品必須是全新狀態與完整包裝(請注意保持商品本體、配件、贈品、保證書、原廠包裝及所有附隨文件或資料的完整性,切勿缺漏任何配件或損毀原廠外盒)。退回商品無法回復原狀者,恐將影響退貨權益或需負擔部分費用。
+
+訂購本商品前請務必詳閱商品退換貨原則。
+
+
+
+
+
+
+