Skip to content

Instantly share code, notes, and snippets.

@YusukeIwaki
Created December 24, 2023 17:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YusukeIwaki/f612435bdaa4441882a48763ea51d609 to your computer and use it in GitHub Desktop.
Save YusukeIwaki/f612435bdaa4441882a48763ea51d609 to your computer and use it in GitHub Desktop.
福岡市総合図書館の会員ページをスクレイピングするためのスクリプト
require 'faraday'
module FukuokaToshokan
class Client
def initialize
default_headers = {
'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
'Accept-Language' => 'ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7',
'Cache-Control' => 'max-age=0',
'Connection' => 'keep-alive',
'Origin' => 'https://opac.toshokan.city.fukuoka.lg.jp',
'Sec-Fetch-Dest' => 'document',
'Sec-Fetch-Mode' => 'navigate',
'Sec-Fetch-Site' => 'same-origin',
'Sec-Fetch-User' => '?1',
'Upgrade-Insecure-Requests' => '1',
'User-Agent' => 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
}
@faraday = Faraday.new(url: 'https://opac.toshokan.city.fukuoka.lg.jp', headers: default_headers, ssl: { verify: false }) do |conn|
conn.request :url_encoded
# conn.response :logger
conn.adapter Faraday.default_adapter
end
end
def login(username, password)
response = @faraday.get('/licsxp-opac/WOpacMnuTopInitAction.do?WebLinkFlag=1&moveToGamenId=mylibrary')
unless response.status == 200
raise "Failed to load login page"
end
@cookie = find_cookie(response, 'JSESSIONID')
response = @faraday.post(
'/licsxp-opac/j_security_check?subSystemFlag=0',
{
hash: '',
gamenid: 'tiles.WMnuTop',
username: username,
j_username: "0000000000000000#{username}",
h_username: '',
j_password: password,
},
{
'Content-Type' => 'application/x-www-form-urlencoded',
'Cookie' => @cookie,
'Referer' => 'https://opac.toshokan.city.fukuoka.lg.jp/licsxp-opac/WOpacMnuTopInitAction.do?WebLinkFlag=1&moveToGamenId=mylibrary',
}
)
unless response.status == 302
raise "Failed to login"
end
if response.headers['set-cookie']
raise "Failed to login"
end
response = @faraday.get('/licsxp-opac/OpacLoginAction.do', {}, {
'Cookie' => @cookie,
'Referer' => 'https://opac.toshokan.city.fukuoka.lg.jp/licsxp-opac/WOpacMnuTopInitAction.do?WebLinkFlag=1&moveToGamenId=mylibrary',
})
unless response.status == 200
raise "Failed to load login page"
end
@cookie = find_cookie(response, 'JSESSIONID')
unless (m = response.body.match(/<input type="hidden" name="hash" value="(?<hash>[^"]+)">/))
raise "Failed to find hash"
end
@hash = m[:hash]
end
private def find_cookie(response, name)
response.headers['set-cookie'].split(';').map(&:strip).find do |cookie|
cookie.start_with?(name)
end
end
def rentals
@faraday.post(
'/licsxp-opac/WOpacUsrLendListAction.do',
{
hash: @hash,
returnid: 'tiles.WMnuTop',
gamenid: 'tiles.WPwdPortalMenuSpl',
tilcod: '',
btnflg: '0',
loccod: '',
itemFlg: '0',
},
{
'Content-Type' => 'application/x-www-form-urlencoded',
'Cookie' => @cookie,
'Referer' => 'https://opac.toshokan.city.fukuoka.lg.jp/licsxp-opac/OpacLoginAction.do',
}
)
end
def reserves
@faraday.post(
'/licsxp-opac/WOpacMnuTopToPwdLibraryAction.do?gamen=usrrsv',
{
hash: @hash,
returnid: 'tiles.WMnuTop',
gamenid: 'tiles.WPwdPortalMenuSpl',
tilcod: '',
btnflg: '0',
loccod: '',
itemFlg: '0',
},
{
'Content-Type' => 'application/x-www-form-urlencoded',
'Cookie' => @cookie,
'Referer' => 'https://opac.toshokan.city.fukuoka.lg.jp/licsxp-opac/OpacLoginAction.do',
}
)
end
end
end
@YusukeIwaki
Copy link
Author

YusukeIwaki commented Dec 24, 2023

usernameとpasswordを用意して、以下のようにすると情報が取れる

    client = Client.new
    client.login(username, password)

    response = client.reserves
    reserves = Nokogiri::HTML(response.body).css('table.list tbody tr').map do |tr|
      tds = tr.css('td')
      title = tds[0].text.strip
      status = tds[6].text.strip
      [title, status]
    end

    response = client.rentals
    rentals = Nokogiri::HTML(response.body).css('table.list tbody tr').map do |tr|
      tds = tr.css('td')
      title = tds[0].text.strip
      return_date = tds[4].text.strip
      [title, return_date]
    end

    [reserves, rentals]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment