설계 및 구현

개발 환경 구축하기

$ rails new HanyangMenu -d mysql
#MySQL로 프로젝트를 생성합니다.

$ rails generate scaffold diet univ_id:integer name:string location:string date:date time:string diet:text extra:text
#전 포스팅에서 작성한 내용대로 테이블 구조를 생성합니다.

$ rake db:create
#database.yml에 설정한대로 데이터베이스를 생성합니다.

$ rake db:migrate
#Migration 파일과 맞는 형태로 스키마 작성 및 테이블 실제 생성합니다.

Controller, Model Unique key, Mysql password

#diets_controller.rb
hanyang = HANYANG.new
hanyang.scarpe
#diet.rb
class Diet < ActiveRecord::Base
  validates :univ_id, :uniqueness => { :scope => [:name, :date, :time, :diet] }
end
#database.yml
default: &default
adapter: mysql2
encoding: utf8
pool: 5
username: root
password: ************ //알아서 은닉화 시켜서 처리하시기 바랍니다.
socket: /tmp/mysql.sock

Hanyang.rb

이 부분은 직접 해당 페이지의 소스를 켜서 분석하면서 보시기 바랍니다. 지금까지 튜토리얼을 모두 보셨다면 하나하나 적을 필요는 없다고 판단합니다. 그리고 이건 정답이 아니고, 이런 식으로 하는 방법이 있다는 것을 알려드릴 뿐입니다.

#app/controllers/HANYANG.rb
class HANYANG
  def initialize
    @default_dates = Array.new  #날짜에 대한 내용을 저장할 배열.
  end
  def scrape
    #이 부분에 Web Scraping 내용을 넣을 예정입니다.
  end
end
#scrape method part#

#한양대학교 에리카캠퍼스 식단 URL
hanyang_erica_url = "https://www.hanyang.ac.kr/upmu/sikdan/sikdan_View.jsp?gb=2&code=2"
#Nokogiri로 <html> 기준으로 파싱
hanyang_erica_data = Nokogiri::HTML(open(hanyang_erica_url))

#Mon to Sun
(0..6).each do |i|  
  #대부분은 월~금가지 제공하지만, 한양대학교는 일요일까지 식단을 제공하는 경우도 있어서 0~6로 처리하였습니다.
  @default_dates << ((Date.parse hanyang_erica_data.css('h3.h3Campus03').text.strip.split('(')[1].split(' ')[0]) + i).to_s
  #2016-06-01 형태로 제공하므로 이걸 Date 형태로 바꾸어 +1씩 하면서, 일요일까지 처리하고 다시 String으로 바꿉니다.
end

#1차 분류(식단을 관리하는 부분으로 갑니다.)
target = hanyang_erica_data.css('div#sikdang table')

content = ""
i = 0  #날짜별 즉, 테이블
target.each do |t|
  p = 0  #각 메뉴별 즉, <td>
  t.css('td').each do |part|
    if (part.nil? || part.text == " ")
      puts "nothing"
    elsif (part.text == "중식" || part.text == "석식")
      puts "nothing"

#각 식단 컨텐츠를 살펴보면, 2개만 있을 때도 있고, 세 가지 이상이 있을 경우가 있습니다. 처음인 요일(날짜)를 제외하고, 그리고 그 다음 조식/중식/석식을 제외하고는 내용 -> 가격 -> 내용 -> 가격 -> 내용 -> 가격 순으로 표가 구성되어 있습니다. 그러므로 홀수는 content, 짝수는 price에 넣습니다. 그리고 price가 채워지는 순간, 하나의 컨텐츠가 완성되므로 바로 튜플 하나를 생성합니다.
    elsif (p % 2 == 1) #홀수
      content = part.text
    elsif (p % 2 == 0) #짝수
      price = part.text.scan(/\d/).join('') #price가 완료되면, 객체 생성
      Diet.create(
        :univ_id => 01,
        :name => "학생식당",
        :location => "복지관 2층",
        :date => @default_dates[i],
        :time => 'lunch',
        #diet는 JSON 형태로 제공하므로, Ruby에서 제공하는 json gem을 이용해서 json처리를 다음과 같이 합니다. 사용하는 gem의 버전과 rails 버전에 따라 방식이 달라지므로, 사용시 주의하시기 바랍니다.
        :diet => JSON.generate({:name => content, :price => price}),
        :extra => ''
        )
    else
      puts "nothing"
      #이 부분은 예외의 상황이나 nil 또는 빈칸으로 컨텐츠가 없을 경우 command 라인에 표시됩니다.
    end
      p += 1
  end
  i += 1
    #금요일까지 했으면 끝, 보통 컨텐츠가 들어있는 부분 이외에도 테이블을 생성해서 유지하고 있는 깔끔하지 않은 페이지들이 있습니다. 그래서 이렇게 하나하나 처리를 해줘야 하는 불편함이 있죠... 생각이 있는 개발자라면, 더 깔끔하게 처리 했을 텐데 아쉽습니다. 다른 학교는 더 가관인 경우가 있습니다. 그래도 한양대학교가 깔끔하게 만든 편은 아니죠... 동덕여대나 덕성여대가 깔끔한 것 같습니다.
  if (i == 5)
    break
  else
  end
end

이해가 안되거나 이상한 점 혹은 질문이 있다면 댓글로 남겨주시면됩니다. 그럼 도움이 되셨기를...
다른 학교 식단을 크롤링하고 싶은데, 궁금한 점이나 어려운 점이 있다면 연락 주시면 아는데까지 설명해 드리겠습니다.
추가로 제가 크롤링 한 식단 중 보고 싶은 거이 있다면, 알려주시면 열어드리겠습니다.
(동덕여대,덕성여대,한성대,한양대,동아대,삼육대,광운대,인하대,명지대)까지 구현 완료했습니다.

results matching ""

    No results matching ""