728x90
nomadcorders의 Go언어 강의를 수강하였습니다.
이 강의는 유튜브에 올라와 있지는 않고
노마드코더스의 아카데미 사이트에만 무료로 공개되고 있습니다.
- Go언어 해당 강의 링크는 아래와 같이,
:=> https://nomadcoders.co/go-for-beginners/lectures/1712
수강하고 마지막에 간단한 프로젝트를 수행하면서 강의를 진행하는데
scrapper 기능을 활용한 프로젝트이다.
해당 강의의 프로젝트 깃허브는,
:=> https://github.com/opensupport-ceo/learngo
이 프로젝트의 핵심 소스인
main.go, scrapper.go, html소스는 아래와 같습니다.
<main.go>
package main
import (
"os"
"strings"
"github.com/labstack/echo"
"github.com/serranoarevalo/learngo/scrapper"
)
const fileName string = "jobs.csv"
func handleHome(c echo.Context) error {
return c.File("home.html")
}
func handleScrape(c echo.Context) error {
defer os.Remove("jobs.csv")
term := strings.ToLower(scrapper.CleanString(c.FormValue("term")))
scrapper.Scrape(term)
return c.Attachment("jobs.csv", "jobs.csv")
}
func main() {
e := echo.New()
e.GET("/", handleHome)
e.POST("/scrape", handleScrape)
e.Logger.Fatal(e.Start(":1323"))
}
<scrapper.go>
package scrapper
import (
"encoding/csv"
"fmt"
"log"
"net/http"
"os"
"strconv"
"strings"
"github.com/PuerkitoBio/goquery"
)
type extractedJob struct {
id string
title string
location string
salary string
summary string
}
// Scrape Indeed by a term
func Scrape(term string) {
var baseURL string = "https://kr.indeed.com/jobs?q=" + term + "&limit=50"
var jobs []extractedJob
c := make(chan []extractedJob)
totalPages := getPages(baseURL)
for i := 0; i < 9; i++ {
go getPage(i, baseURL, c)
}
for i := 0; i < totalPages; i++ {
extractedJobs := <-c
jobs = append(jobs, extractedJobs...)
}
writeJobs(jobs)
fmt.Println("Done, extracted", len(jobs))
}
func getPage(page int, url string, mainC chan<- []extractedJob) {
var jobs []extractedJob
c := make(chan extractedJob)
pageURL := url + "&start=" + strconv.Itoa(page*50)
fmt.Println("Requesting", pageURL)
res, err := http.Get(pageURL)
checkErr(err)
checkCode(res)
defer res.Body.Close()
doc, err := goquery.NewDocumentFromReader(res.Body)
checkErr(err)
searchCards := doc.Find(".jobsearch-SerpJobCard")
searchCards.Each(func(i int, card *goquery.Selection) {
go extractJob(card, c)
})
for i := 0; i < searchCards.Length(); i++ {
job := <-c
jobs = append(jobs, job)
}
mainC <- jobs
}
func extractJob(card *goquery.Selection, c chan<- extractedJob) {
id, _ := card.Attr("data-jk")
title := CleanString(card.Find(".title>a").Text())
location := CleanString(card.Find(".sjcl").Text())
salary := CleanString(card.Find(".salaryText").Text())
summary := CleanString(card.Find(".summary").Text())
c <- extractedJob{
id: id,
title: title,
location: location,
salary: salary,
summary: summary}
}
// CleanString cleans a string
func CleanString(str string) string {
return strings.Join(strings.Fields(strings.TrimSpace(str)), " ")
}
func getPages(url string) int {
pages := 0
res, err := http.Get(url)
checkErr(err)
checkCode(res)
defer res.Body.Close()
doc, err := goquery.NewDocumentFromReader(res.Body)
checkErr(err)
doc.Find(".pagination").Each(func(i int, s *goquery.Selection) {
pages = s.Find("a").Length()
})
return pages
}
func writeJobs(jobs []extractedJob) {
file, err := os.Create("jobs.csv")
checkErr(err)
w := csv.NewWriter(file)
defer w.Flush()
headers := []string{"Link", "Title", "Location", "Salary", "Summary"}
wErr := w.Write(headers)
checkErr(wErr)
for _, job := range jobs {
jobSlice := []string{"https://kr.indeed.com/viewjob?jk=" + job.id, job.title, job.location, job.salary, job.summary}
jwErr := w.Write(jobSlice)
checkErr(jwErr)
}
}
func checkErr(err error) {
if err != nil {
log.Fatalln(err)
}
}
func checkCode(res *http.Response) {
if res.StatusCode != 200 {
log.Fatalln("Request failed with Status:", res.StatusCode)
}
}
<home.html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Go Jobs</title>
</head>
<body>
<h1>Go Jobs</h1>
<h3>Indeed.com scrapper</h3>
<form method="POST" action="/scrape">
<input placeholder="what job do u want" name="term" />
<button>Search</button>
</form>
</body>
</html>
이와 같습니다.
기본동작은 home.html 에서 input으로 입력된 키워드로
main.go에서 scrapper.go 패키지를 이용하여 스크래핑하여
결과를 csv파일로 브라우저에서 저장할 수 있도록 하는 기능입니다.
그럼,
정보 공유합니다.
728x90
'개발 이야기 > Go 언어 이야기' 카테고리의 다른 글
Go 로 만드는 웹 (0) | 2021.05.05 |
---|---|
Awesome Open Source - 대표적인 오픈소스 모아보기 (0) | 2021.05.02 |
Go언어로 하드웨어 및 IoT를? (0) | 2021.04.25 |
Go 언어의 모든 웹프레임워크 모아보기 (0) | 2021.04.24 |
Go 언어의 프레임워크, 라이브러리, 그리고 소프트웨어 (0) | 2021.04.24 |