濮阳杆衣贸易有限公司

主頁 > 知識庫 > 使用Ruby程序?qū)崿F(xiàn)web信息抓取的教程

使用Ruby程序?qū)崿F(xiàn)web信息抓取的教程

熱門標簽:白銀外呼paas系統(tǒng) 地圖標注賺錢項目注冊 百度地圖標注自定義圖片 滴滴外呼系統(tǒng) 高德地圖標注客服 湖州u友防封電銷卡 徐州網(wǎng)絡(luò)外呼系統(tǒng)哪個好 常德電銷平臺外呼系統(tǒng)軟件價格 電銷機器人廠商代理

網(wǎng)站不再單單迎合人類讀者。許多站點現(xiàn)在支持一些 API,這些 API 使計算機程序能夠獲取信息。屏幕抓取 —— 將 HTML 頁面解析為更容易理解的表單的省時技術(shù) — 仍然很方便。但使用 API 簡化 Web 數(shù)據(jù)提取的機會在快速增多。根據(jù) ProgrammableWeb 的信息,在本文發(fā)表時,已存在 10,000 多個網(wǎng)站 API — 在過去的 15 個月中增加了 3,000 個。(ProgrammableWeb 本身提供了一個 API,可從其目錄中搜索和檢索 API、mashup、成員概要文件和其他數(shù)據(jù)。)

本文首先介紹現(xiàn)代的 Web 抓取并將它與 API 方法進行比較。然后通過 Ruby 示例,展示如何使用 API 從一些流行的 Web 屬性中提取結(jié)構(gòu)化信息。您需要基本理解 Ruby 語言、具象狀態(tài)傳輸 (REST),以及 JavaScript 對象表示法 (JSON) 和 XML 概念。
抓取與 API

現(xiàn)在已有多種抓取解決方案。其中一些將 HTML 轉(zhuǎn)換為其他格式,比如 JSON,這樣提取想要的內(nèi)容會更加簡單。其他解決方案讀取 HTML,您可將內(nèi)容定義為 HTML 分層結(jié)構(gòu)的一個函數(shù),其中的數(shù)據(jù)已加了標記。一種此類解決方案是 Nokogiri,它支持使用 Ruby 語言解析 HTML 和 XML 文檔。其他開源抓取工具包括用于 JavaScript 的 pjscrape 和用于 Python 的 Beautiful Soup。pjscrape 實現(xiàn)一個命令行工具來抓取完全呈現(xiàn)的頁面,包括 JavaScript 內(nèi)容。Beautiful Soup 完全集成到 Python 2 和 3 環(huán)境中。

假設(shè)您希望使用抓取功能和 Nokogiri 來識別 CrunchBase 所報告的 IBM 員工數(shù)量。第一步是理解 CrunchBase 上列出了 IBM 員工數(shù)量的特定 HTML 頁面的標記。圖 1 顯示了在 Mozilla Firefox 中的 Firebug 工具中打開的此頁面。該圖的上半部分顯示了所呈現(xiàn)的 HTML,下半部分顯示了感興趣部分的 HTML 源代碼。

清單 1 中的 Ruby 腳本使用 Nokogiri 從圖 1 中的網(wǎng)頁抓取員工數(shù)量。
清單 1. 使用 Nokogiri 解析 HTML (parse.rb)

#!/usr/bin/env ruby
require 'rubygems'
require 'nokogiri'
require 'open-uri'

# Define the URL with the argument passed by the user
uri = "http://www.crunchbase.com/company/#{ARGV[0]}"

# Use Nokogiri to get the document
doc = Nokogiri::HTML(open(uri))

# Find the link of interest
link = doc.search('tr span[1]')

# Emit the content associated with that link
puts link[0].content

在 Firebug 顯示的 HTML 源代碼中(如 圖 1 所示),您可看到感興趣的數(shù)據(jù)(員工數(shù)量)嵌入在一個 HTML 唯一 ID span> 標記內(nèi)。還可看到 span id="num_employees"> 標記是兩個 span> ID 標記中的第一個。所以,清單 1 中的最后兩個指令是,使用 link = doc.search('tr span[1]') 請求第一個 span> 標記,然后使用 puts link[0].content 發(fā)出這個已解析鏈接的內(nèi)容。

CrunchBase 還公開了一個 REST API,它能夠訪問的數(shù)據(jù)比通過抓取功能訪問的數(shù)據(jù)要多得多。清單 2 顯示了如何使用該 API 從 CrunchBase 站點提取公司的員工數(shù)。
清單 2. 結(jié)合使用 CrunchBase REST API 和 JSON 解析 (api.rb)

#!/usr/bin/env ruby
require 'rubygems'
require 'json'
require 'net/http'

# Define the URL with the argument passed by the user
uri = "http://api.crunchbase.com/v/1/company/#{ARGV[0]}.js"

# Perform the HTTP GET request, and return the response
resp = Net::HTTP.get_response(URI.parse(uri))

# Parse the JSON from the response body
jresp = JSON.parse(resp.body)

# Emit the content of interest
puts jresp['number_of_employees']

在清單 2 中,您定義了一個 URL(公司名稱作為腳本參數(shù)傳入)。然后使用 HTTP 類發(fā)出一個 GET 請求并返回響應(yīng)。響應(yīng)被解析為一個 JSON 對象,您可通過一個 Ruby 數(shù)據(jù)結(jié)構(gòu)引用感興趣的數(shù)據(jù)項。

清單 3 中的控制臺會話顯示了運行 清單 1 中的抓取腳本和 清單 2 中基于 API 的腳本的結(jié)果。
清單 3. 演示抓取和 API 方法

$ ./parse.rb ibm
388,000
$ ./api.rb ibm
388000
$ ./parse.rb cisco
63,000
$ ./api.rb cisco
63000
$ ./parse.rb paypal
300,000
$ ./api.rb paypal
300000
$

抓取腳本運行時,您接收一個格式化的計數(shù),而 API 腳本會生成一個原始整數(shù)。如清單 3 所示,您可推廣每種腳本的使用,從 CrunchBase 跟蹤的其他公司請求獲得員工數(shù)。每種方法提供的 URL 的一般結(jié)構(gòu)使這種通用性成為可能。

那么,我們使用 API 方法能獲得什么?對于抓取,您需要分析 HTML 以理解它的結(jié)構(gòu)并識別要提取的數(shù)據(jù)。然后使用 Nokogiri 解析 HTML 并獲取感興趣的數(shù)據(jù)就會很簡單。但是,如果 HTML 文檔的結(jié)構(gòu)發(fā)生變化,您可能需要修改腳本才能正確解析新結(jié)構(gòu)。根據(jù) API 契約,API 方法不存在該問題。API 方法的另一個重要優(yōu)點是,您可訪問通過接口(通過返回的 JSON 對象)公開的所有數(shù)據(jù)。通過 HTML 公開且可供人使用的 CrunchBase 數(shù)據(jù)要少得多。

現(xiàn)在看看如何使用其他一些 API 從 Internet 提取各類信息,同樣要借助 Ruby 腳本。首先看看如何從一個社交網(wǎng)絡(luò)站點收集個人數(shù)據(jù)。然后將看到如何通過其他 API 來源查找更少的個人數(shù)據(jù)。

通過 LinkedIn 提取個人數(shù)據(jù)

LinkedIn 是一個面向?qū)I(yè)職業(yè)的社交網(wǎng)絡(luò)網(wǎng)站。它對聯(lián)系其他開發(fā)人員,尋找工作,研究一家公司,或者加入一個群組,就有趣的主題進行協(xié)作很有用。LinkedIn 還整合了一個推薦引擎,可根據(jù)您的概要文件推薦工作和公司。

LinkedIn 用戶可訪問該站點的 REST 和 JavaScript API,從而獲取可通過其人類可讀網(wǎng)站訪問的信息:聯(lián)系信息、社交分享流、內(nèi)容群組、通信(消息和聯(lián)系邀請),以及公司和工作信息。

要使用 LinkedIn API,您必須注冊您的應(yīng)用程序。注冊后會獲得一個 API 密鑰和秘密秘鑰,以及一個用戶令牌和秘密秘鑰。LinkedIn 使用 OAuth 協(xié)議進行身份驗證。

執(zhí)行身份驗證后,您可通過訪問令牌對象發(fā)出 REST 請求。響應(yīng)是一個典型的 HTTP 響應(yīng),所以您可將正文解析為 JSON 對象。然后可迭代該 JSON 對象來提取感興趣的數(shù)據(jù)。

清單 4 中的 Ruby 腳本為進行身份驗證后的 LinkedIn 用戶提供了要關(guān)注的公司推薦和工作建議。
清單 4. 使用 LinkedIn API (lkdin.rb) 查看公司和工作建議

#!/usr/bin/ruby
require 'rubygems'
require 'oauth'
require 'json'

pquery = "http://api.linkedin.com/v1/people/~?format=json"
cquery='http://api.linkedin.com/v1/people/~/suggestions/to-follow/companies?format=json'
jquery='http://api.linkedin.com/v1/people/~/suggestions/job-suggestions?format=json'
 
# Fill the keys and secrets you retrieved after registering your app
api_key = 'api key'
api_secret = 'api secret'
user_token = 'user token'
user_secret = 'user secret'
 
# Specify LinkedIn API endpoint
configuration = { :site => 'https://api.linkedin.com' }
 
# Use the API key and secret to instantiate consumer object
consumer = OAuth::Consumer.new(api_key, api_secret, configuration)
 
# Use the developer token and secret to instantiate access token object
access_token = OAuth::AccessToken.new(consumer, user_token, user_secret)

# Get the username for this profile
response = access_token.get(pquery)
jresp = JSON.parse(response.body)
myName = "#{jresp['firstName']} #{jresp['lastName']}"
puts "\nSuggested companies to follow for #{myName}"

# Get the suggested companies to follow
response = access_token.get(cquery)
jresp = JSON.parse(response.body)

# Iterate through each and display the company name
jresp['values'].each do | company |
  puts " #{company['name']}"
end

# Get the job suggestions
response = access_token.get(jquery)
jresp = JSON.parse(response.body)
puts "\nSuggested jobs for #{myName}"

# Iterate through each suggested job and print the company name
jresp['jobs']['values'].each do | job |
  puts " #{job['company']['name']} in #{job['locationDescription']}"
end

puts "\n"

清單 5 中的控制臺會話顯示了運行 清單 4 中的 Ruby 腳本的輸出。腳本中對 LinkedIn API 的 3 次獨立調(diào)用有不同的輸出結(jié)果(一個用于身份驗證,其他兩個分別用于公司建議和工作建議鏈接)。
清單 5. 演示 LinkedIn Ruby 腳本

$ ./lkdin.rb

Suggested companies to follow for M. Tim Jones
 Open Kernel Labs, Inc.
 Linaro
 Wind River
 DDC-I
 Linsyssoft Technologies
 Kalray
 American Megatrends
 JetHead Development
 Evidence Srl
 Aizyc Technology

Suggested jobs for M. Tim Jones
 Kozio in Greater Denver Area
 Samsung Semiconductor Inc in San Jose, CA
 Terran Systems in Sunnyvale, CA
 Magnum Semiconductor in San Francisco Bay Area
 RGB Spectrum in Alameda, CA
 Aptina in San Francisco Bay Area
 CyberCoders in San Francisco, CA
 CyberCoders in Alameda, CA
 SanDisk in Longmont, CO
 SanDisk in Longmont, CO

$

可將 LinkedIn API 與任何提供了 OAuth 支持的語言結(jié)合使用。

使用 Yelp API 檢索業(yè)務(wù)數(shù)據(jù)

Yelp 公開了一個富 REST API 來執(zhí)行企業(yè)搜索,包含評分、評論和地理搜索(地段、城市、地理編碼)。使用 Yelp API,您可搜索一種給定類型的企業(yè)(比如 “飯店”)并將搜索限制在一個地理邊界內(nèi);一個地理坐標附近;或者一個鄰居、地址或城市附近。JSON 響應(yīng)包含了與條件匹配的企業(yè)的大量相關(guān)信息,包括地址信息、距離、評分、交易,以及其他類型的信息(比如該企業(yè)的圖片、移動格式信息等)的 URL。

像 LinkedIn 一樣,Yelp 使用 OAuth 執(zhí)行身份驗證,所以您必須向 Yelp 注冊才能通過該 API 獲得一組用于身份驗證的憑據(jù)。腳本完成身份驗證后,可構(gòu)造一個基于 REST 的 URL 請求。在清單 6 中,我硬編碼了一個針對科羅拉多州 Boulder 的飯店請求。響應(yīng)正文被解析到一個 JSON 對象中并進行迭代,從而發(fā)出想要的信息。注意,我排除了已關(guān)閉的企業(yè)。
清單 6. 使用 Yelp API (yelp.rb) 檢索企業(yè)數(shù)據(jù)

#!/usr/bin/ruby
require 'rubygems'
require 'oauth'
require 'json'

consumer_key = 'your consumer key'
consumer_secret = 'your consumer secret'
token = 'your token'
token_secret = 'your token secret'
api_host = 'http://api.yelp.com'

consumer = OAuth::Consumer.new(consumer_key, consumer_secret, {:site => api_host})
access_token = OAuth::AccessToken.new(consumer, token, token_secret)

path = "/v2/search?term=restaurantslocation=Boulder,CO"

jresp = JSON.parse(access_token.get(path).body)

jresp['businesses'].each do | business |
  if business['is_closed'] == false
   printf("%-32s %10s %3d %1.1f\n", 
        business['name'], business['phone'], 
        business['review_count'], business['rating'])
  end
end

清單 7 中的控制臺會話顯示了運行 清單 6 腳本的示例輸出。為了簡單一些,我只顯示了所返回的前面一組企業(yè),而不是支持該 API 的限制/偏移特性(以執(zhí)行多個調(diào)用來檢索整個列表)。這段示例輸出顯示了企業(yè)名稱、電話號碼、收到的評論數(shù)和平均評分。
清單 7. 演示 Yelp API Ruby 腳本

$ ./yelp.rb
Frasca Food and Wine       3034426966 189 4.5
John's Restaurant         3034445232  51 4.5
Leaf Vegetarian Restaurant    3034421485 144 4.0
Nepal Cuisine           3035545828  65 4.5
Black Cat Bistro         3034445500  72 4.0
The Mediterranean Restaurant   3034445335 306 4.0
Arugula Bar E Ristorante     3034435100  48 4.0
Ras Kassa's Ethiopia Restaurant  3034472919 101 4.0
L'Atelier             3034427233  58 4.0
Bombay Bistro           3034444721  87 4.0
Brasserie Ten Ten         3039981010 200 4.0
Flagstaff House          3034424640  86 4.5
Pearl Street Mall         3034493774  77 4.0
Gurkhas on the Hill        3034431355  19 4.0
The Kitchen            3035445973 274 4.0
Chez Thuy Restaurant       3034421700  99 3.5
Il Pastaio            3034479572 113 4.5
3 Margaritas           3039981234  11 3.5
Q's Restaurant          3034424880  65 4.0
Julia's Kitchen                 8 5.0

$

Yelp 提供了一個具有出色文檔的 API,以及數(shù)據(jù)描述、示例、錯誤處理等。盡管 Yelp API 很有用,但它的使用有一定的限制。作為軟件原始開發(fā)人員,您每天最多可執(zhí)行 100 次 API 調(diào)用,出于測試用途可執(zhí)行 1,000 次調(diào)用。如果您的應(yīng)用程序滿足 Yelp 的顯示需求,每天可執(zhí)行 10,000 次調(diào)用(也可能執(zhí)行更多次)。

包含一個簡單 mashup 的域位置

下一個示例將兩段源代碼連接起來,以生成信息。在本例中,您要將一個 Web 域名轉(zhuǎn)換為它的一般地理位置。清單 8 中的 Ruby 腳本使用 Linux? host 命令和 OpenCrypt IP Location API Service 來檢索位置信息。
清單 8. 檢索 Web 域的位置信息

#!/usr/bin/env ruby
require 'net/http'

aggr = ""
key = 'your api key here'

# Get the IP address for the domain using the 'host' command
IO.popen("host #{ARGV[0]}") { | line |
 until line.eof?
  aggr += line.gets
 end
}

# Find the IP address in the response from the 'host' command
pattern = /\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/
if m = pattern.match(aggr)
  uri = "http://api.opencrypt.com/ip/?IP=#{m[0]}key=#{key}"
  resp = Net::HTTP.get_response(URI.parse(uri))
  puts resp.body
end

在清單 8 中,您首先使用本地的 host 命令將域名轉(zhuǎn)換為 IP 地址。(host 命令本身使用一個內(nèi)部 API 和 DNS 解析將域名解析為 IP 地址。)您使用一個簡單的正則表達式(和 match 方法)從 host 命令輸出中解析 IP 地址。有了 IP 地址,就可使用 OpenCrypt 上的 IP 位置服務(wù)來檢索一般地理位置信息。OpenCrypt API 允許您執(zhí)行最多 50,000 次免費 API 調(diào)用。

OpenCrypt API 調(diào)用很簡單:您構(gòu)造的 URL 包含您要定位的 IP 地址和 OpenCrypt 注冊過程提供給您的密鑰。HTTP 響應(yīng)正文包含 IP 地址、國家代碼和國家名稱。

清單 9 中的控制臺會話顯示了兩個示例域名的輸出。
清單 9. 使用簡單的域位置腳本

$ ./where.rb www.baynet.ne.jp
IP=111.68.239.125
CC=JP
CN=Japan
$ ./where.rb www.pravda.ru
IP=212.76.137.2
CC=RU
CN=Russian Federation
$

Google API 查詢

Web API 方面一個無可爭辯的優(yōu)勝者是 Google。Google 擁有如此多的 API,以至于它提供了另一個 API 來查詢它們。通過 Google API Discovery Service,您可列出 Google 提供的可用 API 并提取它們的元數(shù)據(jù)。盡管與大部分 Google API 的交互需要進行身份驗證,但您可通過一個安全套接字連接訪問查詢 API。出于此原因,清單 10 使用 Ruby 的 https 類來構(gòu)造與安全端口的連接。已定義的 URL 指定了 REST 請求,而且響應(yīng)采用了 JSON 編碼。迭代響應(yīng)并發(fā)出一小部分首選的 API 數(shù)據(jù)。
清單 10. 使用 Google API Discovery Service (gdir.rb) 列出 Google API

#!/usr/bin/ruby
require 'rubygems'
require 'net/https'
require 'json'

url = 'https://www.googleapis.com/discovery/v1/apis'

uri = URI.parse(url)

# Set up a connection to the Google API Service
http = Net::HTTP.new( uri.host, 443 )
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE

# Connect to the service
req = Net::HTTP::Get.new(uri.request_uri)
resp = http.request(req)

# Get the JSON representation
jresp = JSON.parse(resp.body)

# Iterate through the API List
jresp['items'].each do | item |
 if item['preferred'] == true
  name = item['name']
  title = item['title']
  link = item['discoveryLink']
  printf("%-17s %-34s %-20s\n", name, title, link)
 end
end

清單 11 中的控制臺會話顯示了運行清單 10 中腳本得到的響應(yīng)示例。
清單 11. 使用簡單的 Google 目錄服務(wù) Ruby 腳本

$ ./gdir.rb
adexchangebuyer  Ad Exchange Buyer API       ./apis/adexchangebuyer/v1.1/rest
adsense      AdSense Management API       ./apis/adsense/v1.1/rest
adsensehost    AdSense Host API          ./apis/adsensehost/v4.1/rest
analytics     Google Analytics API        ./apis/analytics/v3/rest
androidpublisher Google Play Android Developer API ./apis/androidpublisher/v1/rest
audit       Enterprise Audit API        ./apis/audit/v1/rest
bigquery     BigQuery API            ./apis/bigquery/v2/rest
blogger      Blogger API            ./apis/blogger/v3/rest
books       Books API             ./apis/books/v1/rest
calendar     Calendar API            ./apis/calendar/v3/rest
compute      Compute Engine API         ./apis/compute/v1beta12/rest
coordinate    Google Maps Coordinate API     ./apis/coordinate/v1/rest
customsearch   CustomSearch API          ./apis/customsearch/v1/rest
dfareporting   DFA Reporting API         ./apis/dfareporting/v1/rest
discovery     APIs Discovery Service       ./apis/discovery/v1/rest
drive       Drive API             ./apis/drive/v2/rest
...
storage      Cloud Storage API         ./apis/storage/v1beta1/rest
taskqueue     TaskQueue API           ./apis/taskqueue/v1beta2/rest
tasks       Tasks API             ./apis/tasks/v1/rest
translate     Translate API           ./apis/translate/v2/rest
urlshortener   URL Shortener API         ./apis/urlshortener/v1/rest
webfonts     Google Web Fonts Developer API   ./apis/webfonts/v1/rest
youtube      YouTube API            ./apis/youtube/v3alpha/rest
youtubeAnalytics YouTube Analytics API       ./apis/youtubeAnalytics/v1/rest
$

清單 11 中的輸出顯示了 API 名稱、它們的標題,以及進一步分析每個 API 的 URL 路徑。

結(jié)束語

本文中的示例演示了公共 API 在從 Internet 提取信息方面的強大功能。與 Web 抓取和爬取 (spidering) 相比,Web API 提供了訪問有針對性的特定信息的能力。Internet 上在不斷創(chuàng)造新價值,這不僅通過使用這些 API 來實現(xiàn),還通過用新穎的方式組合它們,從而向越來越多的 Web 用戶提供新數(shù)據(jù)來實現(xiàn)。

但是請記住,使用 API 需要付出一定的代價。限制問題就常讓人抱怨。同樣,可能在不通知您的情況下更改 API 規(guī)則這一事實,因此在構(gòu)建應(yīng)用程序時必須加以考慮。最近,Twitter 更改了它的 API 來提供 “一種更加一致的體驗”。這一更改對許多可能被視為典型 Twitter Web 客戶端競爭對手的第三方應(yīng)用程序而言,無疑是一場災(zāi)難。

您可能感興趣的文章:
  • ruby+nokogori抓取糗事百科前10頁并存儲進數(shù)據(jù)庫示例
  • ruby實現(xiàn)網(wǎng)頁圖片抓取
  • Ruby實現(xiàn)網(wǎng)頁圖片抓取

標簽:公主嶺 普洱 三沙 永州 梧州 遼寧 荊門 張家界

巨人網(wǎng)絡(luò)通訊聲明:本文標題《使用Ruby程序?qū)崿F(xiàn)web信息抓取的教程》,本文關(guān)鍵詞  使用,Ruby,程序,實現(xiàn),web,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問題,煩請?zhí)峁┫嚓P(guān)信息告之我們,我們將及時溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《使用Ruby程序?qū)崿F(xiàn)web信息抓取的教程》相關(guān)的同類信息!
  • 本頁收集關(guān)于使用Ruby程序?qū)崿F(xiàn)web信息抓取的教程的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    旬阳县| 延庆县| 桦川县| 凌源市| 始兴县| 山西省| 营山县| 香河县| 兴国县| 鄂尔多斯市| 黎川县| 荃湾区| 即墨市| 绥宁县| 永嘉县| 大悟县| 容城县| 南宁市| 手机| 中卫市| 乌拉特中旗| 墨竹工卡县| 大邑县| 天水市| 五原县| 建水县| 友谊县| 尖扎县| 玉溪市| 安阳县| 兴城市| 盐亭县| 龙州县| 张家界市| 和静县| 阜平县| 阿巴嘎旗| 万州区| 普兰县| 达日县| 富蕴县|