티스토리 뷰
Ruby on Rails : Nokogiri 크롤링 [Gem : nokogiri]
나른한 하루 2019. 12. 5. 06:22해당 글은 https://blog.naver.com/kbs4674/221220959692 로 부터 게시글이 이전되었습니다.
-
크롤링 자료 연결고리
1. Nokogiri를 활용한 크롤링 [클릭]
-
iframe/javascript 기반 사이트에 대해선 크롤링 지원이 안됩니다.
-
selenium에 비해 크롤러가 가볍습니다.
2. Selenium을 활용한 크롤링 [클릭]
-
iframe/javascript 기반 사이트에 대해선 크롤링 지원이 됩니다.
-
Nokogiri에 비해 크롤러가 무겁습니다.
-
Heroku 환경에서는크롬 브라우저에 의존합니다. (Heroku 배포환경에서는 크롬 브라우저 버전에 신경써야 합니다.)
3. Mechanize를 활용한 크롤링 (Nokogiri + 로그인 기능) [클릭]
- Nokogiri에 로그인 기능이 더해진 크롤러 입니다.
- 개인적으로 대체수단(Selenium)이 있는 만큼, 추천드리진 않습니다.
주의사항
크롤링 시 저작권을 잘 따져가면서 하세요!
웹툰, 구직사이트 등의 크롤링은 특히나 주의하셔야 합니다.
사례 사람인에서 잡코리아 크롤링 하다 소송걸린 사례
크롤링에 있어 최소 홈페이지별로 웹수집 봇에게 정보수집을 명시하는 robots.txt에 명시된 규칙을 지켜가며 할 것을 추천드립니다.
예시 티몬의 robots.txt
- 크롤링이란
크롤링이란, 타 사이트에 있는 자료를 수집하는것을 뜻합니다.
예를들면 저같은 경우는 대학 커뮤니티를 기획했는데, 대학 커뮤니티이다 보니 학생들에게 도움이 되는 정보를 제공하고자
학교에 올려져 있는 공지사항, 학식 정보 등을 긁어와서 제공을 해줍니다.
크롤링에 대해 소개 전, 크롤링은 2가지 방식이 있습니다.
1) 일정 시간 간격 크롤링으로 수집한 정보를 내 사이트의 DB에 저장시키고, DB에 저장된 정보를 보여주는 방식
2) 사람들이 방문할 때 마다 바로 크롤링하고, 라이브로 보여주는 방식 (홈페이지 DB저장 X)
1) 같은 경우는 매번 빈번하게 크롤링을 하는게 아니다보니 홈페이지에 큰 무리도 없으나, DB에 크롤링 더미데이터들이 쌓이면 좀 그렇다는 것과, 실시간 방식이 아니라는 단점이 있습니다.
2) 같은 경우는 매번 빈번하게 크롤링을 하다보니 너무 많이 크롤링을 하면 속도가 느려지는 등 홈페이지에 무리는 있으나, 라이브로 자료를 보여주는 장점이 있습니다.
이번 시간에는 위 2개를 둘 다 활용하는 것을 소개하겠습니다.
참고
1. 예약된 시간에 따라 자동으로 일처리를 하는 whenever Gem이 필수적으로 필요합니다.
※ 자동 일처리 : whenever [클릭]
2. whenever Gem에 대한 자세한 설명은 생략합니다.
3. 구글 크롬 브라우저를 활용하면 편합니다.
4. iframe 및 javascript 기반으로 동적으로 운영되는 홈페이지는 크롤링이 안됩니다. (페이스북, 인스타그램 등)
※ 연결고리 : 가상 브라우저 기반 크롤링 [클릭]
준비 보통은 크롤링을 해주는 Nokogiri Gem이 기본적으로 깔려있긴 합니다.
혹시 안깔려 있을 경우는 Gemfile 로 가서
gem 'nokogiri'
를 입력해주세요.
-
DB에 저장하는 방식의 크롤링
저는 예시로 저희 대학 공지사항을 긁어오는 방법에 대해 소개하겠습니다.
[사이트 : http://www.kangwon.ac.kr/www/index.do ]
1. 모델 파일을 만듭니다.
rails g model [모델명] [컬럼]
rails g model notice title campus url
저는 예시로 'crawling_notice' 라는 이름으로 만들겠습니다.
그리고 '공지사항 제목이 들어갈 title, 캠퍼스 이름이 들어갈 campus, 공지사항 URL주소' 3개의 컬럼을 생성하겠습니다.
그리고 Migrate를 해주세요.
rake db:migrate
2. app/model/crawling_notice.rb 파일로 이동 후, 크롤링 수집 시 내용의 중복을 방지하기 위한 코드 한 줄을 써놓습니다.
중복되는 값 구분 기준은 '유일성'을 나타내는 내용이면 좋습니다.
class CrawlingNotice < ApplicationRecord
# validates_uniqueness_of :[DB 컬럼]
validates_uniqueness_of :title
end
3. 다음 명령어를 입력해서 task 파일을 새로 생성해주세요.
# rails g task [task 파일명] [Job 이름]
rails g task crawling notice_collect
참고 lib/tasks 개념 [클릭]
4. lib/tasks/crawling_notice_collect.rake 로 이동하면 다음과 같은 내용으로 되어있을 겁니다.
namespace :crawling do
desc "TODO"
task notice_collect: :environment do
end
end
우리가 구현할 코드 일단 크롤링 코드를 간단하게 보여드리자면 다음과 같습니다.
require 'open-uri'
doc = Nokogiri::HTML(open("[크롤링 홈페이지 대상]")) # 열고
crawl_data = doc.css('[CSS 선택자]')
# 각 row를 돌면서 크롤링 결과를 DB에 저장합니다.
crawl_data.each do |t|
tit = t.css('[CSS]').text
campus = t.css('[CSS]').text
url_extract = t.css('[CSS]').text
url = url_extract['href']
url = url.last(-1)
url_append = "http://www.kangwon.ac.kr/www" + url
[Model 이름].create(title: tit, campus: campus, url: url_append)
end
위 코드를 참고해서, 저희는 캠퍼스 이름, url, 제목이 들어간 정보를 크롤링 해야 합니다.
크롤링을 할 때 있어선 css의 id 및 class 선택자만을 가지고 크롤링이 진행됩니다.
참고 XML(Xpath) 으로도 할 수 있긴 하나, 해당 방법은 초기에 가르치기엔 어려움이 있을 것 같아 생략합니다.
5. 크롤링 사이트 설정을 합니다.
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"))
1번 째 줄에 저희가 크롤링할 대상의 사이트를 적어주세요.
참고 간혹 일부 사이트 같은 경우는 글자가 깨져서 크롤링이 되는 경우가 있습니다. (대표적인 예시로 네이버)
글자가 깨지는 이유는 HTML 표준언어가 다르기 때문인데요, EUC-KR 혹은 UTF-8로 변환을 해줘서 사용하시면 됩니다.
예시 UTF-8로 변환한 경우
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
6. 공지사항의 데이터들 중, 하나의 row를 가지는 css 선택자를 찾아내세요.
저같은 경우는 크롬 브라우저에서 제공하는 개발자도구를 통해 분석해보니 해당 CSS 선택자 위치는
div#tab1_cont > ul.clearfix > li
위 위치로 확인되었습니다.
위 코드를
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
다음과 같이 입력해주세요.
참고 크롤링의 원리는 다음과 같이 진행될 예정입니다 :
1) @posts 변수는 크롤링 대상의 게시물에 있어 div#tab1_cont > ul.clearfix > li 조건에 맞는 전체 내용을 가지고 있다.
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
2) @posts 변수를 쪼개서 하나의 row 단위 별로 데이터를 추출해낸다.
crawl_data.each do |t|
tit = ...
campus = ...
end
7. 이제 전체 데이터 정보를 가진 @crawl_data 변수에서 상세히 쪼개고, 추출하는 과정을 생각해야 합니다.
each do 구문 내 작업을 해보겠습니다.
현재 each do 구문은 과거에 얻어낸 div#tab1_cont > ul.clearfix > li 선택자를 이미 가지고 있는 상태입니다.
그래서 each do 구문 내 선택자를 지정할 땐 div#tab1_cont > ul.clearfix > li 의 하위 선택자만 생각해내면 됩니다.
1) 제목 추출
제목 같은 경우, 아주 간단하게도 a 태그만 지정해주면 됩니다.
tit = t.css('a').text
2) 캠퍼스 추출
캠퍼스 같은 경우 친절하게도, class 선택자가 존재합니다.
span.campus 라고 지정해주면 됩니다.
campus = t.css('span.campus').text
3) URL 추출
URL 추출은 살짝 어려울 수 있습니다.
① 일단 a 태그의 내용에 대해 추출하긴 하나, href 속성 부분까지 크롤링 하도록 지정합니다.
url_extract = t.css('a').at("a[href]")
여기까지 추출하고 결과를 잠깐 살펴보겠습니다.
a태그 자체 및 내용이 한꺼번에 추출이 되네요.
여기까지는 저희가 원하는 방식의 결과물이 아닙니다.
② 기존에 추출한 url 변수 내에서 a태그 내 href 속성만 추출하도록 설정을 합니다.
url = url_extract['href']
이제 뭔가 저희가 원하는 결과물이 나옵니다.
그런데 아직까지도 만족스럽지 않은게, 해당 사이트 같은 경우는 http 및 루트URL 주소가 생략되어 있습니다.
알고보니 홈페이지 설계자가 애초에 http 및 루트URL 주소를 빼먹은 채로 주소가 보여지게 했네요.
③ 일단 url 추출에 대해서 재설계를 해야합니다.
url을 추출 후, 맨 처음에 보이는 점(.)을 없앱니다.
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
④ 마지막으로, 본래의 Root 주소를 append 해줍니다.
url_append = "http://www.kangwon.ac.kr/www" + url
8. 크롤링 코드를 어느정도 짜내면 다음과 같습니다.
한번 제대로 크롤링이 되어있는지 확인하고자 puts 코드도 넣었습니다.
namespace :crawling do
task notice_collect: :environment do
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
# 각 row를 돌면서 크롤링 결과를 DB에 저장합니다.
crawl_data.each do |t|
tit = t.css('a').text
campus = t.css('span.campus').text
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
url_append = "http://www.kangwon.ac.kr/www" + url
puts "[#{campus}] #{tit} || #{url_append}"
end
end
end
9. 한번 제대로 잘 긁어오는지 확인해볼까요?
터미널에 다음 명령어를 입력해서 확인해봅니다.
rake crawling:notice_collect
잘 긁어오는게 확인됩니다 :)
10. 이제 마지막으로 크롤링 한 데이터를 DB에 저장하면 됩니다.
# [Model 이름].create([에트리뷰트]: [내용])
Notice.create(title: @title, campus: @campus, url: @url_swap)
each do 구문 맨 마지막 라인에 위 코드를 넣어주면 끝납니다.
Model에 저장을 하는 최종 코드안은 아래와 같습니다.
namespace :crawling do
task notice_collect: :environment do
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
# 각 row를 돌면서 Result에 추가해줍니다.
crawl_data.each do |t|
tit = t.css('a').text
campus = t.css('span.campus').text
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
url_append = "http://www.kangwon.ac.kr/www" + url
# puts "[#{campus}] #{tit} || #{url_append}"
Notice.create(title: tit, campus: campus, url: url_append)
end
end
end
11. task 파일(Active Job)을 다시한번 작동시킨 후, DB 테이블을 확인해 보면
크롤링한 데이터가 잘 저장된게 확인됩니다.
12. View에다가도 한번 크롤링한 데이터를 불러와볼까요?
터미널에 다음 명령어를 입력해주세요.
rails g controller homes index
라우터에서 Root 설정이 필요하신분은 routes.rb 설정도 해주세요.
## config/routes.rb
root 'homes#index'
13. View 파일에 다음과 같이 내용을 입력해주세요.
<%# app/views/homes/index.html.erb %>
<% Notice.all.each do |t| %>
<div>[<%= t.campus %>] <%= t.title %> <%= link_to "[클릭]", t.url %></div>
<hr/>
<% end %>
14. 홈페이지에서 결과를 보면 아래와 같이 잘 나오는게 확인됩니다.
-
DB에 저장하지 않는 방식의 크롤링
DB에 저장하지 않는 크롤링 방식은 DB에 저장하는 방식의 크롤링에서 Model에 저장하는 과정만 생략됐다고 보시면 됩니다.
저는 예시로 저희 대학 공지사항을 긁어오는 방법에 대해 소개하겠습니다.
[사이트 : http://www.kangwon.ac.kr/www/index.do ]
1. Controller 및 View를 생성합니다.
터미널에 다음 명령어를 입력해주세요.
rails g controller homes index
라우터에서 Root 설정이 필요하신분은 routes.rb 설정도 해주세요.
## config/routes.rb
root 'homes#index'
2. Homes Controller 파일을 열람합니다.
그리고 index 액션 내에서 저희는 크롤링을 하는 코드를 입력해볼 계획입니다.
우리가 구현할 코드 일단 크롤링 코드를 간단하게 보여드리자면 다음과 같습니다.
class HomesController < ApplicationController
def index
require 'open-uri'
doc = Nokogiri::HTML(open("[크롤링 홈페이지 대상]")) # 열고
crawl_data = doc.css('[CSS 선택자]')
# 각 row를 돌면서 배열(@crawlResult)에 추가해줍니다.
@crawlResult = Array.new
crawl_data.each do |t|
title = t.css('[CSS]').text
campus = t.css('[CSS]').text
url_extract = t.css('[CSS]').text
url = url_extract['href']
url_append = "http://www.kangwon.ac.kr/www" + url
@crawlResult.push([campus, title, url_append])
end
end
end
위 코드를 참고해서, 저희는 캠퍼스 이름, url, 제목이 들어간 정보를 크롤링 해야 합니다.
크롤링을 할 때 있어선 css의 id 및 class 선택자만을 가지고 크롤링이 진행됩니다.
참고 XML(Xpath) 으로도 할 수 있긴 하나, 해당 방법은 초기에 가르치기엔 어려움이 있을 것 같아 생략합니다.
3. 크롤링 사이트 설정을 합니다.
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"))
1번 째 줄에 저희가 크롤링할 대상의 사이트를 적어주세요.
참고 간혹 일부 사이트 같은 경우는 글자가 깨져서 크롤링이 되는 경우가 있습니다. (대표적인 예시로 네이버)
글자가 깨지는 이유는 HTML 표준언어가 다르기 때문인데요, EUC-KR 혹은 UTF-8로 변환을 해줘서 사용하시면 됩니다.
예시 UTF-8로 변환한 경우
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
4. 공지사항의 데이터들 중, 하나의 row를 가지는 css 선택자를 찾아내세요.
저같은 경우는 크롬 브라우저에서 제공하는 개발자도구를 통해 분석해보니 해당 CSS 선택자 위치는
div#tab1_cont > ul.clearfix > li
위 위치로 확인되었습니다.
위 코드를
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
다음과 같이 입력해주세요.
참고 크롤링의 원리는 다음과 같이 진행될 예정입니다 :
1) @posts 변수는 크롤링 대상의 게시물에 있어 div#tab1_cont > ul.clearfix > li 조건에 맞는 전체 내용을 가지고 있다.
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
2) @posts 변수를 쪼개서 하나의 row 단위 별로 데이터를 추출해낸다.
crawl_data.each do |t|
title = ...
campus = ...
end
5. 이제 전체 데이터 정보를 가진 @crawl_data 변수에서 상세히 쪼개고, 추출하는 과정을 생각해야 합니다.
each do 구문 내 작업을 해보겠습니다.
현재 each do 구문은 과거에 얻어낸 div#tab1_cont > ul.clearfix > li 선택자를 이미 가지고 있는 상태입니다.
그래서 each do 구문 내 선택자를 지정할 땐 div#tab1_cont > ul.clearfix > li 의 하위 선택자만 생각해내면 됩니다.
1) 제목 추출
제목 같은 경우, 아주 간단하게도 a 태그만 지정해주면 됩니다.
title = t.css('a').text
2) 캠퍼스 추출
캠퍼스 같은 경우 친절하게도, class 선택자가 존재합니다.
span.campus 라고 지정해주면 됩니다.
campus = t.css('span.campus').text
3) URL 추출
URL 추출은 살짝 어려울 수 있습니다.
① 일단 a 태그의 내용에 대해 추출하긴 하나, href 속성 부분까지 크롤링 하도록 지정합니다.
url_extract = t.css('a').at("a[href]")
여기까지 추출하고 결과를 잠깐 살펴보겠습니다.
a태그 자체 및 내용이 한꺼번에 추출이 되네요.
여기까지는 저희가 원하는 방식의 결과물이 아닙니다.
② 기존에 추출한 url 변수 내에서 a태그 내 href 속성만 추출하도록 설정을 합니다.
url = url_extract['href']
이제 뭔가 저희가 원하는 결과물이 나옵니다.
그런데 아직까지도 만족스럽지 않은게, 해당 사이트 같은 경우는 http 및 루트URL 주소가 생략되어 있습니다.
알고보니 홈페이지 설계자가 애초에 http 및 루트URL 주소를 빼먹은 채로 주소가 보여지게 했네요.
③ 일단 url 추출에 대해서 재설계를 해야합니다.
url을 추출 후, 맨 처음에 보이는 점(.)을 없앱니다.
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
④ 마지막으로, 본래의 Root 주소를 append 해줍니다.
url_append = "http://www.kangwon.ac.kr/www" + url
6. 크롤링 코드를 짜내면 다음과 같은 결과물이 나오게 됩니다.
class HomesController < ApplicationController
def index
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
@crawlResult = []
# 각 row를 돌면서 배열(@crawlResult)에 추가해줍니다.
crawlResult = Array.new
crawl_data.each do |t|
title = t.css('a').text
campus = t.css('span.campus').text
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
url_append = "http://www.kangwon.ac.kr/www" + url
@crawlResult.push([campus, title, url_append])
end
end
end
7. View 파일에 다음과 같이 내용을 입력해주세요.
<%# app/views/homes/index.html.erb %>
<% @crawlResult.each do |t| %>
<div>[<%= t[0] %>] <%= t[1] %> <%= link_to "[클릭]", t[2] %></div>
<hr/>
<% end %>
8. 결과를 확인해볼까요!
조금 느리긴 하지만 크롤링 데이터 결과가 나오는게 확인됩니다!
유의사항
데이터를 저장하지 않는 방식의 크롤링은 홈페이지 이용자가 매번 접속 할 때 마다 크롤링이 요청되는 방식이다 보니 홈페이지 퍼포먼스가 많이 떨어질 수 있습니다. 해당 부분에 유의바랍니다.
-
Advanced whenever 설정하기
참고
1. 이 Part는 'DB에 저장하는 방식의 크롤링'을 위한 방법입니다.
2. 예약된 시간에 따라 자동으로 일처리를 하는 whenever Gem이 필수적으로 필요합니다.
※ 자동 일처리 : whenever [클릭]
3. whenever Gem에 대한 자세한 설명은 생략합니다.
1. Gemfile 로 이동하시고, 다음 내용을 입력해서 새로운 Gem을 설치합니다.
gem 'whenever'
2. 프로젝트 상단 위치 /(자신의 프로젝트 위치) 에서 다음 명령어를 입력해줍니다.
wheneverize .
위 명령어를 입력하면 config 디렉토리에 schedule.rb 라는 파일이 생성된 것을 확인하실 수 있습니다.
3. config/schedule.rb 파일을 열람하여, 다음 내용을 (추가) 입력해 줍니다.
## config/schedule.rb
require "tzinfo"
def local(time)
TZInfo::Timezone.get('Asia/Seoul').local_to_utc(Time.parse(time))
end
...
# [매일] 공지사항 크롤링
every :day, at: local('5:10 am') do
# rake "파일이름:Job 이름"
rake "crawling:notice_collect"
end
저는 매일 새벽 5시 10분에 공지사항을 크롤링하게 했습니다.
선택 오랜 기간이 지난 데이터 삭제를 원하신다면, lib/tasks/crawling.rake 로 이동 후, 다음 내용을 추가 입력해주세요.
[Model].where(['created_at <= ?', 3.months.ago]).each do |t|
t.delete
end
저같은 경우, 3달이 지난 데이터는 자동으로 삭제되게 설정했습니다.
namespace :crawling do
task notice_collect: :environment do
require 'open-uri'
doc = Nokogiri::HTML(open("http://www.kangwon.ac.kr/www/index.do"), nil, 'utf-8')
crawl_data = doc.css('div#tab1_cont > ul.clearfix > li')
Notice.where(['created_at <= ?', 3.months.ago]).each do |t|
t.delete
end
# 각 row를 돌면서 Result에 추가해줍니다.
crawl_data.each do |t|
title = t.css('a').text
campus = t.css('span.campus').text
url_extract = t.css('a').at("a[href]")
url = url_extract['href']
url = url.last(-1)
url_append = "http://www.kangwon.ac.kr/www" + url
Notice.create(title: title, campus: campus, url: url_append)
end
end
end
4. /(자기 프로젝트) 로 꼭 이동 후 터미널에 다음 내용을 입력해서
sudo service cron restart
whenever 설정을 최신화 합니다.
5. 그럼 이제 매일 한국시간 기준 새벽 5시 10분에 크롤링이 이뤄지고, 크롤링의 결과물이 DB에 쓰여집니다.
-
참고 .text 메소드
Nokogiri 코드를 작성하면서 .css('') 뒤에 .text 라는 메소드가 붙여져있는것이 있는데요,
저 text 메소드는 문자를 Text형으로 반환하는것을 뜻합니다.
만약에 .text 메소드를 안 붙인 채로 크롤링을 하게 되면..
태그가 훤히 드러난 채로 크롤링이 됩니다.
-
이슈 OpenSSL::SSL::SSLError
크롤러가 https 사이트에 접근 시 보통은 바로 데이터를 읽어들이는데, 이번에 처음으로 위와같은 사례를 겪게되었습니다.
require 'openssl'
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
doc = Nokogiri::HTML(open("https://library.kangwon.ac.kr/#/bbs/ccnotice?offset=0&max=20"))
이 문제의 해결방법은 Nokogiri가 실행 전, 위 두줄의 코드를 사전에 작동을 시키면 됩니다.
-
이슈 Heroku에서 스케쥴러 Job(whenever)이 안됩니다.
해당 이슈에 대해선 https://kbs4674.tistory.com/84 글을 참고해주세요.
-
자료 참고
1. 크롤링 DB 저장방식 [클릭]
2. 라이브 크롤링 방식 [클릭]
3. OpenSSL 에러 [클릭]
'프로그래밍 공부 > Ruby on Rails : Gem' 카테고리의 다른 글
Ruby on Rails : JWT with devise [gem : jwt] (0) | 2019.12.06 |
---|---|
Ruby on Rails : 가상 브라우저를 활용한 크롤링 [Gem : selenium-webdriver] (4) | 2019.12.05 |
Ruby on Rails : DB 백업하기 (PostgresDB 기준 설명) [Gem : backup, whenever] (0) | 2019.12.05 |
Ruby on Rails : 선입선출 Background Job [Gem : sidekiq] (0) | 2019.12.03 |
Ruby on Rails : 스케쥴링(예약된 시간) Background Job [Gem : Whenever] (0) | 2019.12.03 |