コミットを比較
7 コミット
e213a9d393
...
a63b5d223e
作成者 | SHA1 | 日付 |
---|---|---|
守矢諏訪子 | a63b5d223e | |
守矢諏訪子 | 96377a58b4 | |
守矢諏訪子 | ced67abec9 | |
守矢諏訪子 | cf03b347fb | |
守矢諏訪子 | 6fa86399d9 | |
守矢諏訪子 | f375f4f97e | |
守矢諏訪子 | a209cb7714 |
2
Makefile
2
Makefile
|
@ -44,7 +44,7 @@ clean:
|
|||
dist: clean
|
||||
mkdir -p ${NAME}-${VERSION}
|
||||
cp -R LICENSE.txt Makefile README.md CHANGELOG.md\
|
||||
${NAME}.1 *.go go.mod go.sum ${NAME}-${VERSION}
|
||||
${NAME}.1 main.go src go.mod go.sum ${NAME}-${VERSION}
|
||||
tar zcfv ${NAME}-${VERSION}.tar.gz ${NAME}-${VERSION}
|
||||
rm -rf ${NAME}-${VERSION}
|
||||
|
||||
|
|
26
geturl.go
26
geturl.go
|
@ -1,26 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func b2s (val bool) string {
|
||||
if val { return "1" }
|
||||
return "0"
|
||||
}
|
||||
|
||||
func geturl (f Opts) string {
|
||||
date := strings.Split(f.Date, "-")
|
||||
year := date[0]
|
||||
month := date[1]
|
||||
day := date[2]
|
||||
hour := strings.Split(f.Time, ":")[0]
|
||||
minute := strings.Split(f.Time, ":")[1]
|
||||
m1 := string(minute[0])
|
||||
m2 := string(minute[1])
|
||||
|
||||
curl, _ := url.Parse("https://transit.yahoo.co.jp/search/result?from=" + url.QueryEscape(f.From) + "&to=" + url.QueryEscape(f.To) + "&y=" + year + "&m=" + month + "&d=" + day + "&hh=" + hour + "&m1=" + m1 + "&m2=" + m2 + "&type=" + f.Mode + "&ticket=ic&expkind=1&userpass=1&ws=" + f.Route + "&al=" + b2s(f.NoAirplane) + "&shin=" + b2s(f.NoShinkansen) + "&ex=" + b2s(f.NoExpress) + "&hb=" + b2s(f.NoExpressBus) + "&lb=" + b2s(f.NoBus) + "&sr=" + b2s(f.NoFairy))
|
||||
|
||||
return curl.String()
|
||||
}
|
70
main.go
70
main.go
|
@ -4,36 +4,39 @@ import (
|
|||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
"076/norikae/src"
|
||||
)
|
||||
|
||||
var sofname = "norikae"
|
||||
var version = "1.1.0"
|
||||
|
||||
func help () {
|
||||
fmt.Println("076 乗換 - CLIでの路線情報")
|
||||
fmt.Printf("076 乗換 - %s-%s - CLIでの路線情報\n", sofname, version)
|
||||
fmt.Println("https://076.moe/ | https://gitler.moe/suwako/norikae")
|
||||
fmt.Println("\n使い方:")
|
||||
fmt.Println("-v :バージョンを表示")
|
||||
fmt.Println("-h :ヘルプを表示")
|
||||
fmt.Println("-v\n\tバージョンを表示")
|
||||
fmt.Println("-h\n\tヘルプを表示")
|
||||
fmt.Println("\n【必須のオプション】")
|
||||
fmt.Println("-f [出発駅] :例:秋葉原、渋谷、大手町(東京)")
|
||||
fmt.Println("-t [到着駅] :例:秋葉原、渋谷、大手町(東京)")
|
||||
fmt.Println("-f [出発駅]\n\t例:秋葉原、渋谷、大手町(東京)")
|
||||
fmt.Println("-t [到着駅]\n\t例:秋葉原、渋谷、大手町(東京)")
|
||||
fmt.Println("\n【任意のオプション】")
|
||||
fmt.Println("-n [YYYY-MM-DD] :例:2023-05-02(デフォルト:今)")
|
||||
fmt.Println("-j [HH:MM] :例:18:45(デフォルト:今)")
|
||||
fmt.Println("-m [0〜4] :0 = 出発、1 = 指定なし、2 = 終電、3 = 始発、4 = 到着(デフォルト:0)")
|
||||
fmt.Println("-r [0〜2] :0 = 到着が早い順、1 = 料金が高い順、2 = 乗り換え回数順(デフォルト:0)")
|
||||
fmt.Println("--no-airplane :空路を省く")
|
||||
fmt.Println("--no-shinkansen :新幹線を省く")
|
||||
fmt.Println("--no-express :有料特急を省く")
|
||||
fmt.Println("--no-expressbus :高速バスを省く")
|
||||
fmt.Println("--no-bus :路線/連絡バスを省く")
|
||||
fmt.Println("--no-ferry :フェリーを省く")
|
||||
fmt.Println("-n [YYYY-MM-DD]\n\t例:2023-05-02(デフォルト:今)")
|
||||
fmt.Println("-j [HH:MM]\n\t例:18:45(デフォルト:今)")
|
||||
fmt.Println("-m [0〜4]\n\t" +
|
||||
"0 = 出発、1 = 指定なし、2 = 終電、3 = 始発、4 = 到着(デフォルト:0)")
|
||||
fmt.Println("-r [0〜2]\n\t" +
|
||||
"0 = 到着が早い順、1 = 料金が高い順、2 = 乗り換え回数順(デフォルト:0)")
|
||||
fmt.Println("\n--no-airplane\n\t空路を省く")
|
||||
fmt.Println("--no-shinkansen\n\t新幹線を省く")
|
||||
fmt.Println("--no-express\n\t有料特急を省く")
|
||||
fmt.Println("--no-expressbus\n\t高速バスを省く")
|
||||
fmt.Println("--no-bus\n\t路線/連絡バスを省く")
|
||||
fmt.Println("--no-ferry\n\tフェリーを省く")
|
||||
fmt.Println("\n例: " + sofname + " -f 秋葉原 -t 渋谷 -j 16:23 -m 4 --no-bus")
|
||||
}
|
||||
|
||||
func main () {
|
||||
var opts Opts
|
||||
var opts src.Opts
|
||||
// デフォルトな値
|
||||
t := time.Now()
|
||||
opts.Date = t.Format("2006-01-02")
|
||||
|
@ -80,15 +83,32 @@ func main () {
|
|||
if os.Args[i] == "-m" { opts.Mode = os.Args[i+1] }
|
||||
if os.Args[i] == "-r" { opts.Route = os.Args[i+1] }
|
||||
|
||||
if os.Args[i] == "--no-airplane" { opts.NoAirplane = false }
|
||||
if os.Args[i] == "--no-shinkansen" { opts.NoShinkansen = false }
|
||||
if os.Args[i] == "--no-express" { opts.NoExpress = false }
|
||||
if os.Args[i] == "--no-expressbus" { opts.NoExpressBus = false }
|
||||
if os.Args[i] == "--no-bus" { opts.NoBus = false }
|
||||
if os.Args[i] == "--no-ferry" { opts.NoFairy = false }
|
||||
if os.Args[i] == "--no-airplane" {
|
||||
opts.NoAirplane = false
|
||||
}
|
||||
if os.Args[i] == "--no-shinkansen" {
|
||||
opts.NoShinkansen = false
|
||||
}
|
||||
if os.Args[i] == "--no-express" {
|
||||
opts.NoExpress = false
|
||||
}
|
||||
if os.Args[i] == "--no-expressbus" {
|
||||
opts.NoExpressBus = false
|
||||
}
|
||||
if os.Args[i] == "--no-bus" {
|
||||
opts.NoBus = false
|
||||
}
|
||||
if os.Args[i] == "--no-ferry" {
|
||||
opts.NoFairy = false
|
||||
}
|
||||
}
|
||||
|
||||
gurl := geturl(opts)
|
||||
route := scrape(gurl)
|
||||
render(route)
|
||||
gurl, err := src.GetUrl(opts)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
|
||||
route := src.Scrape(gurl)
|
||||
src.Render(route)
|
||||
}
|
||||
|
|
51
render.go
51
render.go
|
@ -1,51 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
func render (route []Route) {
|
||||
var r, g, b uint8
|
||||
col := "fcfcfc"
|
||||
fmt.Sscanf("ff7e56", "%2x%2x%2x", &r, &g, &b)
|
||||
b1 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("早")
|
||||
fmt.Sscanf("60bddb", "%2x%2x%2x", &r, &g, &b)
|
||||
b2 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("楽")
|
||||
fmt.Sscanf("fab60a", "%2x%2x%2x", &r, &g, &b)
|
||||
b3 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("安")
|
||||
fmt.Sscanf(col, "%2x%2x%2x", &r, &g, &b)
|
||||
c := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("")
|
||||
|
||||
for key, value := range route {
|
||||
color.Style{color.FgBlack, color.BgMagenta, color.OpBold}.Println("# ルート" + fmt.Sprintf("%d", key+1))
|
||||
badges := ""
|
||||
for _, badge := range value.Badges {
|
||||
if badge == 1 {
|
||||
badges += "〈" + b1 + "〉"
|
||||
}
|
||||
if badge == 2 {
|
||||
badges += "〈" + b2 + "〉"
|
||||
}
|
||||
if badge == 3 {
|
||||
badges += "〈" + b3 + "〉"
|
||||
}
|
||||
}
|
||||
fmt.Println(value.Time + " (" + value.Duration + "), " + value.Fare + ", 乗換数:" + value.TransitCunt + " " + badges)
|
||||
for k, v := range value.Stations {
|
||||
fmt.Println(v.Time + " " + v.Name)
|
||||
for i, fare := range v.Fares {
|
||||
if k == i {
|
||||
col = fare.Color
|
||||
fmt.Sscanf(col, "%2x%2x%2x", &r, &g, &b)
|
||||
text := fare.Train
|
||||
if fare.Platform != "" { text += "\n" + fare.Platform }
|
||||
c = color.RGB(uint8(r), uint8(g), uint8(b)).Sprint(text)
|
||||
fmt.Println(c)
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
115
scrape.go
115
scrape.go
|
@ -1,115 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
"net"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/gocolly/colly"
|
||||
)
|
||||
|
||||
func scrape (gurl string) []Route {
|
||||
ua := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
|
||||
sc := colly.NewCollector(
|
||||
colly.AllowURLRevisit(),
|
||||
colly.Async(true),
|
||||
)
|
||||
|
||||
sc.WithTransport(&http.Transport {
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
})
|
||||
|
||||
sc.OnRequest(func(r *colly.Request) {
|
||||
r.Headers.Set("User-Agent", ua)
|
||||
r.Headers.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
|
||||
r.Headers.Set("Accept-Language", "en-US,en;q=0.5")
|
||||
})
|
||||
|
||||
sc.OnError(func(_ *colly.Response, err error) {
|
||||
log.Fatal("エラー:", err)
|
||||
})
|
||||
|
||||
var routeArr []Route
|
||||
|
||||
for i := 1; i <= 3; i++ {
|
||||
route := fmt.Sprintf("div#route%02d", i)
|
||||
sc.OnHTML("div.elmRouteDetail " + route, func (e *colly.HTMLElement) {
|
||||
Routes := Route{}
|
||||
e.ForEach("div.routeSummary div ul.priority li span", func (j int, el *colly.HTMLElement) {
|
||||
if el.Attr("class") == "icnPriTime" {
|
||||
Routes.Badges = append(Routes.Badges, 1)
|
||||
}
|
||||
if el.Attr("class") == "icnPriFare" {
|
||||
Routes.Badges = append(Routes.Badges, 2)
|
||||
}
|
||||
if el.Attr("class") == "icnPriTrans" {
|
||||
Routes.Badges = append(Routes.Badges, 3)
|
||||
}
|
||||
})
|
||||
base := e.ChildText("ul.summary li.time span")
|
||||
time := strings.ReplaceAll(base, e.ChildText("ul.summary li.time span.small"), "")
|
||||
time2 := strings.Split(time, "着")
|
||||
Routes.Time = time2[0] + "着"
|
||||
durabase := e.ChildText("ul.summary li.time")
|
||||
durasi := strings.Index(durabase, "着") + len("着")
|
||||
duraei := strings.Index(durabase[durasi:], "分") + len("分") + durasi
|
||||
|
||||
Routes.Duration = durabase[durasi:duraei]
|
||||
Routes.TransitCunt = strings.ReplaceAll(e.ChildText("ul.summary li.transfer"), "乗換:", "")
|
||||
Routes.Fare = strings.ReplaceAll(e.ChildText("ul.summary li.fare"), "[priic]IC優先:", "")
|
||||
Stations := Station{}
|
||||
Fares := Fare{}
|
||||
Stops := Stop{}
|
||||
e.ForEach("div.routeDetail div.station", func (j int, el *colly.HTMLElement) {
|
||||
Stations.Time = el.ChildText("ul.time li")
|
||||
if el.ChildText("p.icon span") == "[dep]" { Stations.Time += "発" }
|
||||
if el.ChildText("p.icon span") == "[arr]" { Stations.Time += "着" }
|
||||
Stations.Name = el.ChildText("dl dt a")
|
||||
e.ForEach("div.routeDetail div.fareSection div.access", func (jf int, elf *colly.HTMLElement) {
|
||||
Fares.Stops = nil
|
||||
if jf == j {
|
||||
Fares.Train = strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(strings.ReplaceAll(elf.ChildText("li.transport div"), "[train]", "【電車】"), "[bus]", "【バス】"), "[air]", "【空路】"), "当駅始発", "【当駅始発】") + " "
|
||||
|
||||
Fares.Platform = elf.ChildText("li.platform")
|
||||
Fares.Color = strings.ReplaceAll(elf.ChildAttr("span", "style"), "border-color:#", "")
|
||||
elf.ForEach("li.stop ul", func (js int, els *colly.HTMLElement) {
|
||||
Stops.Time = els.ChildText("li dl dt")
|
||||
Stops.Name = strings.ReplaceAll(els.ChildText("li dl dd"), "○", "")
|
||||
Fares.Stops = append(Fares.Stops, Stops)
|
||||
})
|
||||
Stations.Fares = append(Stations.Fares, Fares)
|
||||
}
|
||||
})
|
||||
e.ForEach("div.routeDetail div.walk ul.info", func (jw int, elw *colly.HTMLElement) {
|
||||
if jw == j {
|
||||
Fares.Train = strings.ReplaceAll(elw.ChildText("li.transport"), "[line][walk]", "")
|
||||
Fares.Platform = ""
|
||||
Fares.Color = "a8a8a8"
|
||||
Stations.Fares = append(Stations.Fares, Fares)
|
||||
}
|
||||
})
|
||||
Routes.Stations = append(Routes.Stations, Stations)
|
||||
})
|
||||
|
||||
routeArr = append(routeArr, Routes)
|
||||
})
|
||||
}
|
||||
|
||||
sc.Visit(gurl)
|
||||
sc.Wait()
|
||||
|
||||
return routeArr
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package src
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
func b2s (val bool) string {
|
||||
if val { return "1" }
|
||||
return "0"
|
||||
}
|
||||
|
||||
func GetUrl (f Opts) (string, error) {
|
||||
date := strings.Split(f.Date, "-")
|
||||
year := date[0]
|
||||
month := date[1]
|
||||
day := date[2]
|
||||
hour := strings.Split(f.Time, ":")[0]
|
||||
minute := strings.Split(f.Time, ":")[1]
|
||||
m1 := string(minute[0])
|
||||
m2 := string(minute[1])
|
||||
|
||||
curl, err := url.Parse(
|
||||
"https://transit.yahoo.co.jp/search/result" +
|
||||
"?from=" + url.QueryEscape(f.From) +
|
||||
"&to=" + url.QueryEscape(f.To) +
|
||||
"&y=" + year +
|
||||
"&m=" + month +
|
||||
"&d=" + day +
|
||||
"&hh=" + hour +
|
||||
"&m1=" + m1 +
|
||||
"&m2=" + m2 +
|
||||
"&type=" + f.Mode +
|
||||
"&ticket=ic&expkind=1&userpass=1&ws=" + f.Route +
|
||||
"&al=" + b2s(f.NoAirplane) +
|
||||
"&shin=" + b2s(f.NoShinkansen) +
|
||||
"&ex=" + b2s(f.NoExpress) +
|
||||
"&hb=" + b2s(f.NoExpressBus) +
|
||||
"&lb=" + b2s(f.NoBus) +
|
||||
"&sr=" + b2s(f.NoFairy))
|
||||
if err != nil {
|
||||
return "", nil
|
||||
}
|
||||
|
||||
return curl.String(), nil
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package src
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gookit/color"
|
||||
)
|
||||
|
||||
var r, g, b uint8
|
||||
var col string
|
||||
|
||||
func getFares(v Station, k int) {
|
||||
c := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("")
|
||||
|
||||
for i, fare := range v.Fares {
|
||||
if k != i { continue }
|
||||
|
||||
col = fare.Color
|
||||
fmt.Sscanf(col, "%2x%2x%2x", &r, &g, &b)
|
||||
text := fare.Train
|
||||
|
||||
if fare.Platform != "" { text += "\n" + fare.Platform }
|
||||
c = color.RGB(uint8(r), uint8(g), uint8(b)).Sprint(text)
|
||||
fmt.Println(c)
|
||||
}
|
||||
}
|
||||
|
||||
func Render (route []Route) {
|
||||
col = "fcfcfc"
|
||||
|
||||
fmt.Sscanf("ff7e56", "%2x%2x%2x", &r, &g, &b)
|
||||
b1 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("早")
|
||||
|
||||
fmt.Sscanf("60bddb", "%2x%2x%2x", &r, &g, &b)
|
||||
b2 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("楽")
|
||||
|
||||
fmt.Sscanf("fab60a", "%2x%2x%2x", &r, &g, &b)
|
||||
b3 := color.RGB(uint8(r), uint8(g), uint8(b)).Sprint("安")
|
||||
|
||||
fmt.Sscanf(col, "%2x%2x%2x", &r, &g, &b)
|
||||
|
||||
for key, value := range route {
|
||||
color.Style{
|
||||
color.FgBlack,
|
||||
color.BgMagenta,
|
||||
color.OpBold,
|
||||
}.Println("# ルート" + fmt.Sprintf("%d", key+1))
|
||||
|
||||
badges := ""
|
||||
for _, badge := range value.Badges {
|
||||
if badge == 1 { badges += "〈" + b1 + "〉" }
|
||||
if badge == 2 { badges += "〈" + b2 + "〉" }
|
||||
if badge == 3 { badges += "〈" + b3 + "〉" }
|
||||
}
|
||||
|
||||
fmt.Println(
|
||||
value.Time + " (" + value.Duration + "), " +
|
||||
value.Fare + ", 乗換数:" + value.TransitCunt + " " + badges,
|
||||
)
|
||||
|
||||
for k, v := range value.Stations {
|
||||
fmt.Println(v.Time + " " + v.Name)
|
||||
getFares(v, k)
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
}
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
package src
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/gocolly/colly"
|
||||
)
|
||||
|
||||
func getSummary(i int, e *colly.HTMLElement) Route {
|
||||
r := Route{}
|
||||
if e.Attr("class") == "icnPriTime" { r.Badges = append(r.Badges, 1) }
|
||||
if e.Attr("class") == "icnPriFare" { r.Badges = append(r.Badges, 2) }
|
||||
if e.Attr("class") == "icnPriTrans" { r.Badges = append(r.Badges, 3) }
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func handleFare(el *colly.HTMLElement, f Fare, s Stop) Fare {
|
||||
fixTrain := strings.ReplaceAll(
|
||||
el.ChildText("li.transport div"), "[train]", "【電車】",
|
||||
)
|
||||
fixBus := strings.ReplaceAll(fixTrain, "[bus]", "【バス】")
|
||||
fixAir := strings.ReplaceAll(fixBus, "[air]", "【空路】")
|
||||
fixEki := strings.ReplaceAll(fixAir, "当駅始発", "【当駅始発】")
|
||||
|
||||
f.Train = fixEki
|
||||
f.Platform = el.ChildText("li.platform")
|
||||
f.Color = strings.ReplaceAll(el.ChildAttr("span", "style"), "border-color:#", "")
|
||||
el.ForEach("li.stop ul", func (js int, els *colly.HTMLElement) {
|
||||
s.Time = els.ChildText("li dl dt")
|
||||
s.Name = strings.ReplaceAll(els.ChildText("li dl dd"), "○", "")
|
||||
f.Stops = append(f.Stops, s)
|
||||
})
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func handleWalk(el *colly.HTMLElement, f Fare) Fare {
|
||||
f.Train = strings.ReplaceAll(
|
||||
el.ChildText("li.transport"), "[line][walk]", "",
|
||||
)
|
||||
f.Platform = ""
|
||||
f.Color = "a8a8a8"
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func getRouteDetail(e *colly.HTMLElement) Route {
|
||||
r := Route{}
|
||||
onDivs := "div.routeSummary div ul.priority li span"
|
||||
e.ForEach(onDivs, func(i int, el *colly.HTMLElement) {
|
||||
summary := getSummary(i, el)
|
||||
r.Badges = append(r.Badges, summary.Badges...)
|
||||
})
|
||||
|
||||
base := e.ChildText("ul.summary li.time span")
|
||||
time := strings.ReplaceAll(base, e.ChildText("ul.summary li.time span.small"), "")
|
||||
time2 := strings.Split(time, "着")
|
||||
r.Time = time2[0] + "着"
|
||||
durabase := e.ChildText("ul.summary li.time")
|
||||
durasi := strings.Index(durabase, "着") + len("着")
|
||||
duraei := strings.Index(durabase[durasi:], "分") + len("分") + durasi
|
||||
|
||||
r.Duration = durabase[durasi:duraei]
|
||||
r.TransitCunt = strings.ReplaceAll(
|
||||
e.ChildText("ul.summary li.transfer"), "乗換:", "",
|
||||
)
|
||||
r.Fare = strings.ReplaceAll(
|
||||
e.ChildText("ul.summary li.fare"), "[priic]IC優先:", "",
|
||||
)
|
||||
|
||||
Stations := Station{}
|
||||
Fares := Fare{}
|
||||
Stops := Stop{}
|
||||
|
||||
onDivs = "div.routeDetail div.station"
|
||||
e.ForEach(onDivs, func (j int, el *colly.HTMLElement) {
|
||||
Stations.Time = el.ChildText("ul.time li")
|
||||
if el.ChildText("p.icon span") == "[dep]" { Stations.Time += "発" }
|
||||
if el.ChildText("p.icon span") == "[arr]" { Stations.Time += "着" }
|
||||
Stations.Name = el.ChildText("dl dt a")
|
||||
|
||||
onDivs = "div.routeDetail div.fareSection div.access"
|
||||
e.ForEach(onDivs, func (jf int, elf *colly.HTMLElement) {
|
||||
Fares.Stops = nil
|
||||
if jf != j { return }
|
||||
f := handleFare(elf, Fares, Stops)
|
||||
Stations.Fares = append(Stations.Fares, f)
|
||||
})
|
||||
|
||||
onDivs = "div.routeDetail div.walk ul.info"
|
||||
e.ForEach(onDivs, func (jw int, elw *colly.HTMLElement) {
|
||||
if jw != j { return }
|
||||
f := handleWalk(elw, Fares)
|
||||
Stations.Fares = append(Stations.Fares, f)
|
||||
})
|
||||
r.Stations = append(r.Stations, Stations)
|
||||
})
|
||||
|
||||
return r
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package src
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
"net"
|
||||
"fmt"
|
||||
|
||||
"github.com/gocolly/colly"
|
||||
)
|
||||
|
||||
func Scrape (gurl string) []Route {
|
||||
ua := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " +
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) " +
|
||||
"Chrome/110.0.0.0 Safari/537.36"
|
||||
|
||||
sc := colly.NewCollector(
|
||||
colly.AllowURLRevisit(),
|
||||
colly.Async(true),
|
||||
)
|
||||
|
||||
sc.WithTransport(&http.Transport {
|
||||
Proxy: http.ProxyFromEnvironment,
|
||||
DialContext: (&net.Dialer{
|
||||
Timeout: 30 * time.Second,
|
||||
KeepAlive: 30 * time.Second,
|
||||
DualStack: true,
|
||||
}).DialContext,
|
||||
ForceAttemptHTTP2: true,
|
||||
MaxIdleConns: 100,
|
||||
IdleConnTimeout: 90 * time.Second,
|
||||
TLSHandshakeTimeout: 10 * time.Second,
|
||||
ExpectContinueTimeout: 1 * time.Second,
|
||||
})
|
||||
|
||||
sc.OnRequest(func(r *colly.Request) {
|
||||
r.Headers.Set("User-Agent", ua)
|
||||
r.Headers.Set(
|
||||
"Accept",
|
||||
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
)
|
||||
r.Headers.Set("Accept-Language", "en-US,en;q=0.5")
|
||||
})
|
||||
|
||||
sc.OnError(func(_ *colly.Response, err error) {
|
||||
log.Fatal("エラー:", err)
|
||||
})
|
||||
|
||||
var routeArr []Route
|
||||
|
||||
for i := 1; i <= 3; i++ {
|
||||
route := fmt.Sprintf("div#route%02d", i)
|
||||
sc.OnHTML("div.elmRouteDetail " + route, func (e *colly.HTMLElement) {
|
||||
Routes := getRouteDetail(e)
|
||||
routeArr = append(routeArr, Routes)
|
||||
})
|
||||
}
|
||||
|
||||
sc.Visit(gurl)
|
||||
sc.Wait()
|
||||
|
||||
return routeArr
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package main
|
||||
package src
|
||||
|
||||
type (
|
||||
Opts struct {
|
読み込み中…
新しいイシューから参照