2010-11-01 26 views
1

我正在重新格式化多個汽車經銷商的庫存管理器的搜索查詢的HTML輸出格式。沒有直接的數據庫訪問,服務創建者沒有任何信息,所以我決定嘗試使用Nokogiri解析和重新格式化數據,並基於搜索查詢生成新的結果頁面。使用Nokogiri&Sinatra解析和重新格式化數據的最有效方法

在第一次加載頁面時,我只是使用默認搜索來生成第一個結果。

對於搜索工作,我將查詢發送到一個URL是這樣的:

post '/search/?:search_query' do 
    url = "http://domain.com/v/?DealerId=" + settings.dealer_id + "&maxrows=10&#{params[:search_query]}" 
    doc = Nokogiri::HTML(open(url)) 
    doc.css("td:nth-child(5) .ForeColor4").each do |msrp| 
    session["msrp"] = msrp.inner_html 
    end 
    doc.css("td:nth-child(4) .ForeColor4").each do |price| 
    session["price"] = price.inner_html 
    end 
    erb :index  
end 

我知道一定是做到這一點的明智之選。

編輯:

一個例子URL來請求數據:

http://domain.com/?DealerId=1234&object=list&lang=en&MAKE=&MODEL=&maxrows=50&MinYear=&MaxYear=2011&Type=N&MinPrice=&MaxPrice=&STYLE=&ExtColor=&MaxMiles=&StockNo= 

產生的HTML的描述:

不幸的是,它的舊代碼這是幾乎完全表爲基礎的,具有inline-風格和大多數地區缺乏類或ID。

CSS選擇器的一個例子:

td:nth-child(5) .ForeColor4 

一個XPath選擇:

//td[(((count(preceding-sibling::*) + 1) = 5) and parent::*)]//*[contains(concat(" ", @class, " "), concat(" ", "ForeColor4", " "))] 

我也看了機械化或角度來說,Hpricot的可能性,但我不知道的最好的工具因爲我之前沒有嘗試過屏幕截圖。

摘要:我想從HTML提取數據,暫時將其存儲在一個變量/會話/餅乾(數據更改每天幾次),然後能夠輸出重新格式化爲我自己的HTML/CSS樣式。

+1

我不確定有一個更聰明的方法來做到這一點,因爲您沒有真正給我們足夠的背景或數據來處理。什麼是你正在檢索的網址或頁面的HTML是什麼樣的? – 2010-11-02 00:42:27

+0

我已經添加了一些更多的細節/示例,謝謝讓我知道什麼會有所幫助。 – 2010-11-02 00:51:59

+0

如果您需要通過表單或登錄導航站點,機械化非常棒。這是您在刮取HTML的個別頁面的折騰。我個人喜歡open-uri和Nokogiri,對於我所做的大部分工作。有更好但更復雜的HTTP客戶端比open-uri,但是Nokogiri很難被擊敗。一個好的替代HTTP客戶端是['Typhoeus'](http://www.pauldix.net/2009/01/ruby-http-client-library-performance.html)。 – 2010-11-02 02:07:02

回答

1

就我個人而言,我會從用戶操作中解耦出來。有一個獨立的進程刮擦並填充您的數據庫。這將大大提高性能,因爲提取,創建DOM,解析,然後渲染每個動作的輸出將會很慢。

+0

經銷商將增加和刪除他們的庫存(我每天被告知幾次),因此,當我仍然需要檢查每次更改時,將所有內容放在數據庫中似乎對我來說過分殺傷了。 – 2010-11-02 01:25:30

+0

@Anders H:是的,你可以隨心所欲地檢查,但你不必花費用戶的時間。除非您的用戶願意交易緩慢的響應時間,以瞭解他們的信息是否屬於最新信息。 – 2010-11-02 10:47:22

+0

這是一個很好的觀點。如果我每天只重建數據庫幾次,那麼發生任何變化的可能性很小。我感謝你的意見。 – 2010-11-02 19:19:32

0
 
    doc.css("td:nth-child(5) .ForeColor4").each do |msrp| 
    session["msrp"] = msrp.inner_html 
    end 
    doc.css("td:nth-child(4) .ForeColor4").each do |price| 
    session["price"] = price.inner_html 
    end 

您可能需要使用引入nokogiri的at_css()方法,而不是常規的css()的。 at_css()找到您的目標的第一個匹配項,並且只返回一個節點,類似於針對.css()返回的節點集執行.first

這將簡化您的查找,以這種形式:

session["msrp"] = doc.at_css("td:nth-child(5) .ForeColor4").inner_html 

我可能會添加類似rescue 'msrp lookup failed',而只是在你有不好的情況下存取測試在查找結束。或者,當inner_html()生氣試圖從零讀取時,您可能會讓代碼失敗。這只是一個更友好的調試方式。

否則你的查找看起來很體面。

+0

我不得不使用.css我相信,因爲每頁有(最多)10個搜索結果。所以「td:nth-​​child(5).ForeColor4」選擇器實際上適用於10個元素。 我想我只是不確定我是否試圖做太多沒有使用數據庫或PStore或如果我忽略了一個更簡單的方法。 – 2010-11-02 00:53:40

+0

我同意馬克托馬斯,支持數據庫是一個好主意。您的後端代碼將作爲crontab作業運行,例如每四六個小時運行一次。您可以詢問他們的服務器是否更改了內容,或者對檢索到的html進行校驗和,並確定是否需要處理它。將結果緩存在數據庫中。另一個應用程序會在需要時從數據庫返回當前結果。 – 2010-11-02 02:03:38

+0

呵呵,如果你不熟悉它,HTTP頭部請求就是你用來查看文檔是否發生了變化。 'ETag'和/或'Last-Modified'標題將成爲你的朋友。 – 2010-11-02 02:19:19

相關問題