儲存大量連結的正確方法?
我正在對多個站點進行小型爬網,並且我有很多由 ID (
example.com/foo
=354
) 表示的連結。我目前正在儲存
link -> link
參考資料和連結文本。因此,在下表頁面“2845”中包含一個指向 4479 的連結,其中包含文本“About Us”。沒什麼大不了的,只有3NF。+----------+----------+-----------------+ | url_1_id | url_2_id | text | +----------+----------+-----------------+ | 2845 | 4479 | About Us | | 2845 | 4480 | Who We Are | | 2845 | 4481 | What We Do | | 2845 | 4482 | Core Principles | | 2845 | 4483 | Research Staff | +----------+----------+-----------------+
但是,根據我的計算(大多數頁面每個包含 500-1000 個連結),當我只解析 200k 個頁面時,我應該有 6GB 的連結數據。
有沒有更好的方法來儲存連結數據?特別是如果有一種很好的方法來規範所有網站頁面的重複導航菜單。
如果您不能或不會使用 Graph DB(它應該是此類應用程序的最佳 DB),那麼您可以測試數據的稍微抽象的分解。這是我對您的任務採取的一種方法。
首先,您有特定的 URL 連結。例如,在另一個答案的末尾可以找到指向joanolo的連結https://dba.stackexchange.com/users/112361/joanolo 。一個頁面上可能有多個這樣的連結(即 joanolo 的評論每個都有相同的連結)。您想如何處理頁面上的多個相同連結?我選擇以特定方式處理相同的連結,如下所述。我定義表來處理 URL 連結,如下所示:
CREATE TABLE URLLinks ( URLLinksID bigint identity(1,1), URLParams nvarchar(max) NULL, URLsID bigint not null, secure bit default 0 not null, CONSTRAINT pk_URLLINKS Primary Key (URLsID, URLParams, Secure) )
請注意,URL 連結包括連結上的任何參數,以及連接是否安全。對於這第一遍,我忽略了其他類型的連結,例如 ftp://
URLLinks 表中的 URLsID 欄位是對 URLs 表的引用。這包含 URL 的文本,例如
dba.stackexchange.com/users/112361/joanolo
在上面的範例 URL 中。任何將此作為 URL 的連結都將通過 URLsID 引用此 URL 條目。這是非常簡單的 URL 表:CREATE TABLE URLs ( URLsID bigint identity(1,1), URLText nvarchar(max) not null )
在這兩個表之間,我們擁有重新創建 URL 所需的所有資訊,包括任何參數,而無需複制 URLText。
請注意,如果值得的話,我們可以將 URLText 分解成一個更小的片段鏈,並建構一個將正確片段連結在一起的 URL 鏈。我敢打賭,這個連結,一個 8 字節的 ID 指向每個片段,父片段(如果有)和鏈(24 字節 + 成本)將比使用 URL 文本在空間和成本上更昂貴直接,所以我現在不探索那條路。
要將連結與其頁面關聯,可以使用 URLRefs 表:
URLRefs ( URLID bigint not null, ParentURLID bigint not null, LinkText nvarchar(max) not null, LinkCount int default 1 not null )
注意欄位
LinkCount
。這將計算頁面上出現相同 URLLink 的次數,而不是每次出現都有單獨的條目。這可能會或可能不會總體上節省空間和精力,但它確實可以在 dba.stackexchange.com 上聽到,所以我採用了這種方法。在頁面上從不重複連結的網站上,這將始終為 1。使用這些元素,您應該擁有最緊湊的非圖形描述頁面,其中 URL 指向頁面,而 URL 指向…(除非您建構特殊情況來處理例如菜單,如 joanolo 建議的那樣。)
例如,上面顯示的 joanolo 連結在 URLLinks 中只有一個條目,在 URLs 中只有一個條目,在 URLRefs 中對於連結出現的每個不同頁面都有一個條目。如果他在 100 個頁面中有 500 個這樣的連結,那麼他在 URL 和 URLLinks 中仍然只有一個連結,在 URLRefs 中只有 100 個條目。
可能的方法:
- 如果您的問題可以通過圖表很好地表示(我認為是),我建議您考慮使用Graph Database。它針對這種場景進行了優化:您有頁面(節點),您有頁面之間的連結(頂點),並且您有一些與其中任何一個相關聯的屬性。檢查Neo4J或OrientDB以了解它們在您的場景中可以做什麼。
- 如果您想節省一些空間,請考慮一種以緊湊方式表示*菜單的方法。*也就是說,會有非常多的情況,比如:
page1 - links_to - home
page1 - links_to - legalese page1
- links_to - the_company
page1 - links_to - our_products
page1 - links_to - our_services
page1 - links_to - 聯繫人
page1 - links_to - 獨特或不常見的東西 1
page1 - links_to - 獨特或不常見的東西 2
然後再一次
(第 2 頁相同)
(第 3 頁相同)
如果你確定了這個結構,你可以創建一些“元結構”,比如“standard_menu”。(這種方法的困難部分是決定哪些連結集合應該被視為菜單,哪些不是,以及小的差異,例如包含略有變化的菜單的頁面
$$ such as “I don’t link to myself” $$).
這個資料結構應該可以幫助你:
CREATE TABLE urls ( id_url serial PRIMARY KEY, url text NOT NULL, UNIQUE(url) ) ; CREATE TABLE menus ( id_menu serial PRIMARY KEY ) ; CREATE TABLE menu_links ( id_menu integer not null REFERENCES menus(id_menu), id_url_to integer not null REFERENCES urls(id_url), link_text text not null, PRIMARY KEY (id_menu, id_url_to) ) ; CREATE TABLE from_page_to_page ( id_url_from integer not null REFERENCES urls(id_url), id_url_to integer not null REFERENCES urls(id_url), link_text text not null, PRIMARY KEY (id_url_from, id_url_to, link_text) ) ; CREATE TABLE from_page_to_menu ( id_url_from integer not null REFERENCES urls(id_url), id_menu integer not null REFERENCES menus(id_menu), PRIMARY KEY (id_url_from, id_menu) ) ;
最後,您可以通過創建“菜單連結”和“非菜單連結”的 UNION 來獲得將現有表的等價物組合在一起的視圖:
CREATE VIEW all_links AS SELECT id_url_from, id_url_to, link_text FROM from_page_to_page UNION ALL SELECT id_url_from, id_url_to, link_text FROM from_page_to_menu JOIN menu_links ON menu_links.id_menu = from_page_to_menu.id_menu ;
或者,每次你有類似的東西時,你總是可以通過“link_group”更改名稱“menu”:
page1 - links_to - page_a
page1 - links_to - page_b
page1 - links_to - page_c
page1 - links_to - page_z
page2 - links_to - page_a
page2 - links_to - page_b
page2 - links_to - page_c
page2 - links_to - page_y
page3 - links_to
page_a page3 - links_to - page_b page3 - links_to
page_c page3
links_to - page_x
(忽略文本標籤,這些實際上是 12 對數字)
您可以將其轉換為:
link_grup_1 - page_a
link_grup_1 - page_b
link_grup_1 - page_c
page_1 - link_grup - link_grup_1
page_1 - links_to - page_z page_2 - link_grup
link_grup_1 page_2
links_to - page_y
page_3 - link_grup - link_grup_1
page_3 - links_to - page_x
(這些只是 9 對數字)。
一旦許多頁面共有的項目數量超過兩個或三個,節省的費用就會增加。