| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568 |
- package controller
- import (
- "crawler/config"
- "crawler/model"
- "crawler/service"
- "crawler/utility"
- "github.com/gin-gonic/gin"
- "github.com/gocolly/colly"
- "log"
- "net"
- "net/http"
- "time"
- )
- type MovieController interface {
- SearchDailyBoxOfficeList(c *gin.Context)
- SearchWeeklylyBoxOfficeList(c *gin.Context)
- SearchMovieList(c *gin.Context)
- }
- type Movie struct {
- MovieListModel model.MovieListModel
- MovieDailyModel model.MovieDailyModel
- MovieWeeklyModel model.MovieWeeklyModel
- MovieInfoModel model.MovieInfoModel
- MovieSearchModel model.MovieSearchModel
- MovieDetailModel model.MovieDetailModel
- Kobis model.Kobis
- Rest service.Rest
- }
- // GET SearchDailyBoxOfficeList
- func (this *Movie) SearchDailyBoxOfficeList(c *gin.Context) {
- var req = this.MovieDailyModel.SearchDailyBoxOfficeParams
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- var (
- total, rows = 0, 0
- list = make([]model.MovieDailyTable, 0)
- )
- // 검색 변수 생성
- params, err := this.MovieDailyModel.MakeParams(req)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색값이 있는지 확인
- ids, err := this.MovieSearchModel.SelectIDs(params)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색 내역이 있음
- if ids != "" {
- // DB에서 먼저 조회해본다.
- list, err = this.MovieDailyModel.List(ids)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- }
- // 목록이 없으면 API 호출
- if len(list) <= 0 {
- data, err := this.Kobis.MovieDailyBoxOfficeListAPI(req)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- }
- // 데이터 새로 입력
- if len(data.BoxOfficeResult.DailyBoxOfficeList) > 0 {
- if err = this.MovieDailyModel.Insert(data); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- var movieCd []string
- for _, row := range data.BoxOfficeResult.DailyBoxOfficeList {
- movieCd = append(movieCd, row.MovieCd)
- }
- lastInsertIds, _ := this.MovieDailyModel.LastInsertIDs(movieCd, req.TargetDt)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색 결과 저장
- movieSearch := this.MovieSearchModel.MovieSearch
- movieSearch.Params = params
- movieSearch.IDs = lastInsertIds
- if err = this.MovieSearchModel.Insert(movieSearch); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- if lastInsertIds != "" {
- list, err = this.MovieDailyModel.List(lastInsertIds)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- }
- }
- }
- // 상세 정보를 조회해서 저장한다.
- for i, row := range list {
- row.Detail, _ = this.FindMovieDetail(row.MovieCd)
- list[i] = row
- rows++
- }
- total = this.MovieDailyModel.Total()
- c.JSON(http.StatusOK, gin.H{
- "total": total,
- "rows": rows,
- "list": list,
- })
- }
- // GET SearchWeeklylyBoxOfficeList
- func (this *Movie) SearchWeeklyBoxOfficeList(c *gin.Context) {
- var req = this.MovieWeeklyModel.SearchWeeklyBoxOfficeParams
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- var (
- total, rows = 0, 0
- list = make([]model.MovieWeeklyTable, 0)
- )
- // 검색 변수 생성
- params, err := this.MovieWeeklyModel.MakeParams(req)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색값이 있는지 확인
- ids, err := this.MovieSearchModel.SelectIDs(params)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색 내역이 있음
- if ids != "" {
- // DB에서 먼저 조회해본다.
- list, err = this.MovieWeeklyModel.List(ids)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- }
- // 목록이 없으면 API 호출
- if len(list) <= 0 {
- data, err := this.Kobis.MovieWeeklyBoxOfficeListAPI(req)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- }
- // 데이터 새로 입력
- if len(data.BoxOfficeResult.WeeklyBoxOfficeList) > 0 {
- if err = this.MovieWeeklyModel.Insert(data); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- var movieCd []string
- for _, row := range data.BoxOfficeResult.WeeklyBoxOfficeList {
- movieCd = append(movieCd, row.MovieCd)
- }
- lastInsertIds, _ := this.MovieWeeklyModel.LastInsertIDs(movieCd, req.TargetDt)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- // 검색 결과 저장
- movieSearch := this.MovieSearchModel.MovieSearch
- movieSearch.Params = params
- movieSearch.IDs = lastInsertIds
- if err = this.MovieSearchModel.Insert(movieSearch); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- if lastInsertIds != "" {
- list, err = this.MovieWeeklyModel.List(lastInsertIds)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- }
- }
- }
- // 상세 정보를 조회해서 저장한다.
- for i, row := range list {
- row.Detail, _ = this.FindMovieDetail(row.MovieCd)
- list[i] = row
- rows++
- }
- total = this.MovieWeeklyModel.Total()
- c.JSON(http.StatusOK, gin.H{
- "total": total,
- "rows": rows,
- "list": list,
- })
- }
- // GET SearchMovieList
- func (this *Movie) SearchMovieList(c *gin.Context) {
- var req = this.MovieListModel.SearchMovieListParams
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- type result = struct {
- MovieListInfo model.MovieListInfo `json:"summary"`
- Info *model.MovieInfoTable `json:"info"`
- Detail *model.MovieDetailTable `json:"detail"`
- }
- var (
- total, rows = 0, 0
- list = make([]result, 0)
- )
- data, err := this.Kobis.MovieListAPI(req)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- }
- // 데이터 새로 입력
- if data.MovieListResult.TotCnt > 0 {
- if err = this.MovieListModel.Insert(data.MovieListResult.MovieList); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- }
- // 기본, 상세 정보를 조회해서 저장한다.
- for _, row := range data.MovieListResult.MovieList {
- info, _ := this.FindMovieInfo(req.Key, row.MovieCd)
- detail, _ := this.FindMovieDetail(row.MovieCd)
- list = append(list, result{
- MovieListInfo: row,
- Info: info,
- Detail: detail,
- })
- rows++
- }
- total = this.MovieListModel.Total()
- c.JSON(http.StatusOK, gin.H{
- "total": total,
- "rows": rows,
- "list": list,
- })
- }
- /**
- * 영화 일별 박스오피스 정보 조회
- * /movie/searchDailyInfo
- */
- func (this *Movie) SearchDailyInfo(c *gin.Context) {
- var req = struct {
- Key string `form:"key" binding:"required"`
- DailyID int `form:"dailyID" binding:"required"`
- }{}
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- stats, err := this.MovieDailyModel.Info(req.DailyID)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- if stats.DailyID == 0 {
- c.JSON(http.StatusBadRequest, "잘못된 요청입니다.")
- return
- }
- info, err := this.FindMovieInfo(req.Key, stats.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- detail, err := this.FindMovieDetail(stats.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- c.JSON(http.StatusOK, gin.H{
- "stats": stats,
- "info": info,
- "detail": detail,
- })
- }
- /**
- * 영화 주간/주말 박스오피스 정보 조회
- * /movie/searchWeeklyInfo
- */
- func (this *Movie) SearchWeeklyInfo(c *gin.Context) {
- var req = struct {
- Key string `form:"key" binding:"required"`
- WeeklyID int `form:"weeklyID" binding:"required"`
- }{}
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- stats, err := this.MovieWeeklyModel.Info(req.WeeklyID)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- if stats.WeeklyID == 0 {
- c.JSON(http.StatusBadRequest, "잘못된 요청입니다.")
- return
- }
- info, err := this.FindMovieInfo(req.Key, stats.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- detail, err := this.FindMovieDetail(stats.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- c.JSON(http.StatusOK, gin.H{
- "stats": stats,
- "info": info,
- "detail": detail,
- })
- }
- /**
- * 영화 정보 조회
- * /movie/searchMovieInfo
- */
- func (this *Movie) SearchMovieInfo(c *gin.Context) {
- var req = this.MovieInfoModel.SearchMovieInfoParams
- if err := c.ShouldBind(&req); err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- info, err := this.FindMovieInfo(req.Key, req.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- detail, err := this.FindMovieDetail(req.MovieCd)
- if err != nil {
- c.JSON(http.StatusBadRequest, err.Error())
- return
- }
- c.JSON(http.StatusOK, gin.H{
- "info": info,
- "detail": detail,
- })
- }
- // 영화 기본 정보 조회
- func (this *Movie) FindMovieInfo(key, movieCd string) (*model.MovieInfoTable, error) {
- if this.MovieListModel.IsExists(movieCd) == false || this.MovieInfoModel.IsExists(movieCd) == false {
- req := this.MovieInfoModel.SearchMovieInfoParams
- req.Key = key
- req.MovieCd = movieCd
- data, err := this.Kobis.MovieInfoAPI(req)
- if err != nil {
- return nil, err
- }
- err = this.MovieListModel.Replace(model.MovieListInfo{
- MovieCd: data.MovieInfoResult.MovieInfo.MovieCd,
- MovieNm: data.MovieInfoResult.MovieInfo.MovieNm,
- MovieNmEn: data.MovieInfoResult.MovieInfo.MovieNmEn,
- PrdtYear: data.MovieInfoResult.MovieInfo.PrdtYear,
- OpenDt: data.MovieInfoResult.MovieInfo.OpenDt,
- TypeNm: data.MovieInfoResult.MovieInfo.TypeNm,
- PrdtStatNm: data.MovieInfoResult.MovieInfo.PrdtStatNm,
- NationAlt: "",
- GenreAlt: "",
- RepNationNm: "",
- RepGenreNm: "",
- Directors: nil,
- Companys: nil,
- })
- if err != nil {
- return nil, err
- }
- // 영화 기본 정보 입력
- this.MovieInfoModel.Insert(data.MovieInfoResult.MovieInfo)
- if err != nil {
- return nil, err
- }
- }
- movieInfo, err := this.MovieInfoModel.Info(movieCd)
- return &movieInfo, err
- }
- // 영화 주요 정보 조회
- func (this *Movie) FindMovieDetail(movieCd string) (*model.MovieDetailTable, error) {
- if this.MovieDetailModel.IsExists(movieCd) == false {
- movieDetail := this.MovieDetailModel.MovieDetail
- movieDetail.MovieCd = movieCd
- // c2 := c1.Clone()
- c1 := colly.NewCollector(
- colly.AllowedDomains(config.KOBIS_DOMAIN),
- colly.IgnoreRobotsTxt(),
- colly.Async(false),
- )
- c1.WithTransport(&http.Transport{
- DialContext: (&net.Dialer{
- Timeout: 30 * time.Second,
- KeepAlive: 30 * time.Second,
- }).DialContext,
- MaxIdleConns: 0,
- IdleConnTimeout: 10 * time.Second,
- TLSHandshakeTimeout: 10 * time.Second,
- ExpectContinueTimeout: 10 * time.Second,
- })
- c1.OnRequest(func(r *colly.Request) {
- r.Headers.Set("User-Agent", utility.RandomString())
- r.Headers.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
- })
- c1.OnError(func(_ *colly.Response, err error) {
- log.Printf("Error(c1) : %s\n", err.Error())
- })
- /*
- 관객 수, 누적 매출액 조회
- */
- /*
- c2.OnRequest(func(r *colly.Request) {
- r.Headers.Set("User-Agent", utility.RandomString())
- r.Headers.Set("Content-Type", "application/x-www-form-urlencoded;charset=UTF-8")
- })
- c2.OnError(func(_ *colly.Response, err error) {
- log.Printf("Error(c2) : %s\n", err.Error())
- })
- */
- c1.OnHTML(".item_tab.basic", func(e *colly.HTMLElement) {
- var host = config.KOBIS_HOST
- movieDetail.MainImg = e.ChildAttr("a.fl.thumb", "href")
- if movieDetail.MainImg != "" && movieDetail.MainImg != "#" {
- movieDetail.MainImg = host + movieDetail.MainImg
- }
- movieDetail.ThumbImg = e.ChildAttr("a.fl.thumb > img", "src")
- if movieDetail.ThumbImg != "" && movieDetail.ThumbImg != "#" {
- movieDetail.ThumbImg = host + movieDetail.ThumbImg
- }
- movieDetail.Synopsis = e.ChildText("div.info.info2 p.desc_info")
- e.ForEach("div#post > input", func(_ int, ee *colly.HTMLElement) {
- movieDetail.Poster = append(movieDetail.Poster, model.Poster{
- Thumb: host + ee.Attr("thn_img"),
- Origin: host + ee.Attr("img"),
- })
- })
- e.ForEach("div#stl > input", func(_ int, ee *colly.HTMLElement) {
- movieDetail.StillCut = append(movieDetail.StillCut, model.StillCut{
- Thumb: host + ee.Attr("thn_img"),
- Origin: host + ee.Attr("img"),
- })
- })
- })
- /*
- c2.OnHTML("body", func(e *colly.HTMLElement) {
- var (
- tr = e.DOM.Find(".info").Eq(0).Find("table tbody tr").Eq(1)
- saleAcc = utility.RemoveSpecialChar(strings.Replace(tr.Find("td").Eq(2).Text(), "(100%)", "", 1))
- audiAcc = utility.RemoveSpecialChar(strings.Replace(tr.Find("td").Eq(3).Text(), "(100%)", "", 1))
- )
- SaleAcc, _ := strconv.Atoi(saleAcc)
- AudiAcc, _ := strconv.Atoi(audiAcc)
- movieDetail.SaleAcc = SaleAcc
- movieDetail.AudiAcc = AudiAcc
- })
- */
- err := c1.Post(config.MOVIE_DETAIL, map[string]string{
- "code": movieCd,
- "sType": "",
- "titleYN": "Y",
- "etcParam": "",
- "isOuterReq": "false",
- })
- if this.Rest.Check(err) {
- return nil, err
- }
- /*
- err = c2.Post(config.MOVIE_DETAIL, map[string]string{
- "code": movieCd,
- "sType": "stat",
- })
- if this.Rest.Check(err) {
- return nil, err
- }
- */
- err = this.MovieDetailModel.Insert(movieDetail)
- if this.Rest.Check(err) {
- return nil, err
- }
- }
- movieDetail, err := this.MovieDetailModel.Info(movieCd)
- return &movieDetail, err
- }
|