Yahoo! Query Language (YQL)
This post hasn't been updated for 4 years
Yahoo! Query Language (YQL) được tạo bởi Yahoo!, nó là một ngôn ngữ truy vấn giống với SQL. Nó cho phép chúng ta truy vấn, lọc và kết hợp dữ liệu giữa các website với nhau thông qua một ngôn ngữ đơn giản nhất.
Các tính năng tiêu biểu của YQL:
- Truy cập dữ liệu thông qua web
- Chọn, lọc, sắp xếp và nối dữ liệu qua các dịch vụ web. Thậm chí bạn có thể thêm, sửa và xóa từ YQL.
- Tăng tốc độ thực thi ứng dụng
- Với YQL, các ứng dụng chạy nhanh hơn với ít dòng code và một mạng lưới đánh dấu (footprint) nhỏ hơn.
- Dễ dàng khai thác HTML
- Khai thác HTML từ các website để biến nó thành dữ liệu để tái sử dụng. Tạo API từ các website không hỗ trợ API (non-official API).
- Ghép các nguồn dữ liệu
- Trộn và kết hợp dữ liệu từ các nguồn khác nhau bằng cách sử dụng YQL sub-selects.
- Chuyển đổi XML sang JSON
- YQL có thể chuyển đổi XML sang JSON và ngược lại. Truy cập Atom, RSS hoặc nhiều hơn thế. Thậm chí bạn có thể tải các tập tin CSV từ bất kỳ đâu.
- Tính mở rộng
- Định nghĩa các bảng dữ liệu mở (Open data tables) để truy cập mọi nguồn dữ liệu khác Yahoo Web Services
Để bắt đầu với YQL, các bạn có thể truy cập vào YQL Console để xem và test các ví dụ chi tiết hơn. Còn bài viết này mình chỉ giới thiệu qua về YQL và cái mình chú trọng vào nhất sẽ ở phần Tạo API từ các website không hỗ trợ API nhé !
Mình sẽ hướng dẫn mọi người viết một non-official API đơn giản bằng JavaScript (mình sẽ viết bằng CoffeeScript, còn code JS thì mọi người vào link source code ở cuối bài để xem phần compiled) nhé. Trong bài này, mình sẽ sử dụng trang NhacCuaTui để làm ví dụ. API này có hai việc chính là nhận từ khóa (tên bài hát, ca sỹ, người upload, ...) rồi trả về danh sách các bài hát tương ứng và nhận đường dẫn bài hát rồi trả về link trực tiếp (direct link) của bài hát đó. Okie, let's go!
Chúng ta tạo hẳn một class với tên NhacCuaTui cho hịn nhé )!
NhacCuaTui = ->
Trong class này có một private object chứa hai phần tử là URL của YQL và URL tìm kiếm của NhacCuaTui (mình sử dụng domain dành cho mobile để có tốc độ truy xuất nhanh hơn):
_apiSettings =
apiURL: "http://m.nhaccuatui.com/tim-kiem/bai-hat?q="
endpointURL: "https://query.yahooapis.com/v1/public/yql?q="
Tiếp theo, chúng ta sẽ có một private function để truy xuất dữ liệu từ YQL, hàm này sẽ nhận câu truy vấn và trả về object dữ liệu từ YQL:
_yqlExecuteQuery = (yqlStatement) ->
yqlResult = {}
$.ajax
url: "#{_apiSettings.endpointURL}#{encodeURIComponent yqlStatement}&format=json"
cache: no
async: no
success: (response) ->
yqlResult = response
error: (xmlHttpReq, ajaxOpts, error) ->
console.log error
yqlResult
Tiếp theo đến public function search, nhận tham số là từ khóa và trả về một object chứa danh sách kết quả tìm được:
@search = (keyword) ->
# Mã hóa từ khóa sang dạng URI #
keyword = encodeURIComponent keyword.trim()
# Object chứa status và mảng object kết quả #
result =
status: false
items: []
if keyword isnt ""
yqlStatement = "SELECT * FROM html WHERE url='#{_apiSettings.apiURL + keyword}' AND xpath='//div[contains(@class, \"bgmusic\")]'"
yqlResult = _yqlExecuteQuery yqlStatement
if yqlResult.query.count > 0
result.status = true
$.each yqlResult.query.results.div, (idx, item) ->
result.items.push
title: item.h3.a.title
link: item.h3.a.href
artist: item.p.content
listen: item.p.span.content
result
Xong phần tìm kiếm. Bây giờ đến phần lấy direct link của bài hát. Public function này sẽ nhận tham số là link bài hát và trả về object chứa trạng thái với direct link của bài hát đó:
@get = (link) ->
result =
status: false
link: ""
if link.trim() isnt ""
yqlStatement = "SELECT * FROM html WHERE url='#{link}' AND xpath='//div[@class=\"download\"]//a'"
yqlResult = _yqlExecuteQuery yqlStatement
if yqlResult.query.count > 0
result =
status: true
link: yqlResult.query.results.a.href
result
Vậy là xong rồi. Bây giờ chúng ta sẽ thử test API của mình nhé. Mình sẽ sử dụng React.JS để test. Từ khi quen viết React.JS mình rất ngại sửa HTML DOM bằng jQuery !
###* @jsx React.DOM ###
SearchBar = React.createClass
_onClickSearchButtonHandler: ->
keyword = @refs.keyword.getDOMNode().value.trim()
if keyword isnt ""
@props.searchSong keyword
else
alert "Please enter keyword."
render: ->
# Trong source và demo không có dấu ` ` trước và sau thẻ input và button nhé #
`(
<div className="search-bar">
`<input type="text" placeholder="Song name, artist, user, ..." ref="keyword" />`
`<button onClick={this._onClickSearchButtonHandler}>Search</button>`
</div>
)`
SongList = React.createClass
render: ->
songList = @props.songList || []
SongElement = `(<div className="song">
<p className="title">(no data)</p>
</div>)`
if songList.length > 0
SongElement = songList.map ((song, idx) ->
`(<Song songInfo={song} getSong={this.props.getSong} />)`
).bind @
`(
<div className="song-list">
{SongElement}
</div>
)`
Song = React.createClass
_onClickSongHandler: (link) ->
@props.getSong link
render: ->
songInfo = @props.songInfo
`(
<div className="song" onClick={this._onClickSongHandler.bind(null, songInfo.link)}>
<p className="title">{songInfo.title}</p>
<p>
<span className="artist">{songInfo.artist}</span>
<span className="listen">{songInfo.listen}</span>
</p>
</div>
)`
Player = React.createClass
componentDidUpdate: (prevProps, prevState) ->
videoElement = @refs.videoElement.getDOMNode()
videoElement.load()
videoElement.play()
render: ->
songLink = @props.link || ""
`(
<div id="player">
<audio controls autoplay ref="videoElement">
<source src={songLink} type="audio/mpeg" />
Your browser does not support the audio element.
</audio>
</div>
)`
App = React.createClass
getInitialState: ->
songList: []
songLink: ""
componentWillMount: ->
@nhacCuaTui = new NhacCuaTui()
_searchSong: (keyword) ->
songList = @nhacCuaTui.search keyword
if songList.status
@setState
songList: songList.items
_getSong: (link) ->
songLink = @nhacCuaTui.get link
if songLink.status
@setState
songLink: songLink.link
render: ->
`(
<div id="wrapper">
<SearchBar searchSong={this._searchSong} />
<SongList songList={this.state.songList} getSong={this._getSong} />
<Player link={this.state.songLink} />
</div>
)`
React.renderComponent `<App />`, document.body
Các bạn có thể xem demo và source code tại hai địa chỉ sau:
Trên đây mình đã giới thiệu với mọi người về YQL và cũng như cách để viết một API của riêng mình. Trước khi viết, mọi người nên quan tâm đến việc bản quyền nội dung nhé. Demo và source của mình chỉ có mục đích để giới thiệu thôi nhé !
Bài viết gốc: https://namnv609.cf/posts/yahoo-query-language-yql.html
All Rights Reserved