@@ -3,6 +3,7 @@ package commands
33import (
44 "crypto/tls"
55 "fmt"
6+ "log"
67 "net/http"
78 "net/url"
89 "regexp"
@@ -70,21 +71,17 @@ func init() {
7071 RootCmd .PersistentFlags ().String ("cache" , "" , "Cache directory" )
7172 RootCmd .PersistentFlags ().Bool ("parallel" , false , "Fetch in parallel" )
7273 RootCmd .PersistentFlags ().Bool ("images" , true , "Download images" )
74+ RootCmd .MarkFlagRequired ("url" )
7375
7476 // Bind command-line flags to Viper
75- viper .BindPFlag ( "dir" , RootCmd .PersistentFlags (). Lookup ( "dir" ))
76- viper . BindPFlag ( "url" , RootCmd . PersistentFlags (). Lookup ( "url" ))
77- viper . BindPFlag ( "cache" , RootCmd . PersistentFlags (). Lookup ( "cache" ) )
78- viper . BindPFlag ( "images" , RootCmd . PersistentFlags (). Lookup ( "images" ))
77+ err := viper .BindPFlags ( RootCmd .PersistentFlags ())
78+ if err != nil {
79+ log . Fatal ( err )
80+ }
7981
8082 viper .AutomaticEnv ()
8183 viper .EnvKeyReplacer (strings .NewReplacer ("-" , "_" ))
8284 viper .SetEnvPrefix ("WGS" )
83-
84- // Execute root command
85- if err := RootCmd .Execute (); err != nil {
86- fmt .Println (err )
87- }
8885}
8986
9087func rootCmdF (command * cobra.Command , args []string ) error {
@@ -103,9 +100,9 @@ func rootCmdF(command *cobra.Command, args []string) error {
103100
104101 scrape .c .Async = parallel
105102
106- // Ignore SSL errors
103+ // Use a custom TLS config to verify server certificates
107104 scrape .c .WithTransport (& http.Transport {
108- TLSClientConfig : & tls.Config {InsecureSkipVerify : true },
105+ TLSClientConfig : & tls.Config {},
109106 })
110107
111108 parsedURL , err := url .Parse (commandURL )
@@ -120,31 +117,44 @@ func rootCmdF(command *cobra.Command, args []string) error {
120117 // On every a element which has href attribute call callback
121118 scrape .c .OnHTML ("a[href]" , func (e * colly.HTMLElement ) {
122119 link := e .Attr ("href" )
123- scrape .visitURL (e . Request . AbsoluteURL ( link ) )
120+ scrape .visitURL (link )
124121 })
125122
126123 // On every link element call callback
127124 scrape .c .OnHTML ("link[href]" , func (e * colly.HTMLElement ) {
128125 link := e .Attr ("href" )
129- scrape .visitURL (e . Request . AbsoluteURL ( link ) )
126+ scrape .visitURL (link )
130127 })
131128
132129 // On every script element call callback
133130 scrape .c .OnHTML ("script[src]" , func (e * colly.HTMLElement ) {
134131 link := e .Attr ("src" )
135- scrape .visitURL (e . Request . AbsoluteURL ( link ) )
132+ scrape .visitURL (link )
136133 })
137134
138135 // On every img element call callback
139-
140136 scrape .c .OnHTML ("img" , func (e * colly.HTMLElement ) {
141- link := e .Attr ("src" )
142- scrape .visitURL (e .Request .AbsoluteURL (link ))
137+ src := e .Attr ("src" )
138+ srcSet := e .Attr ("srcset" )
139+ scrape .visitURL (src )
140+
141+ if srcSet != "" {
142+ srcSetList := strings .Split (srcSet , "," )
143+ for _ , srcSetURL := range srcSetList {
144+ srcSetURL = strings .TrimSpace (srcSetURL )
145+ innerSrcSet := strings .Split (srcSetURL , " " )[0 ]
146+ if innerSrcSet == "" {
147+ continue
148+ }
149+
150+ scrape .visitURL (innerSrcSet )
151+ }
152+ }
143153 })
144154
145155 // Before making a request print "Visiting ..."
146156 scrape .c .OnRequest (func (r * colly.Request ) {
147- fmt .Println ("Visiting" , r .URL .String ())
157+ log .Println ("Visiting" , r .URL .String ())
148158 })
149159
150160 // On response
@@ -154,7 +164,7 @@ func rootCmdF(command *cobra.Command, args []string) error {
154164
155165 err := file .SaveFile (r , dir , fileName )
156166 if err != nil {
157- fmt .Println (err )
167+ log .Println (err )
158168 return
159169 }
160170 })
@@ -172,15 +182,38 @@ func rootCmdF(command *cobra.Command, args []string) error {
172182}
173183
174184func (s * Scrape ) visitURL (link string ) {
175- // Download image found on page if it hasn't been visited before
185+ link = s .getAbsoluteURL (link )
186+
187+ if link == "" {
188+ return
189+ }
190+
191+ u , err := url .Parse (link )
192+ if err != nil {
193+ log .Printf ("Error parsing URL %s: %s" , link , err )
194+ return
195+ }
196+
197+ if u .Scheme == "" || u .Host == "" {
198+ log .Printf ("Invalid URL %s" , link )
199+ return
200+ }
201+
202+ u .Fragment = ""
203+
204+ link = u .String ()
205+
206+ // Download page if it hasn't been visited before
176207 if ! s .urlCache .Get (link ) {
177208 s .urlCache .Add (link )
178- s .c .Visit (link )
209+ err := s .c .Visit (link )
210+ if err != nil {
211+ log .Println (err )
212+ }
179213 }
180214}
181215
182216func (s * Scrape ) parseBody (body []byte ) []byte {
183- // Find all URLs in the CSS file
184217 cssUrls := regexp .MustCompile (`url\((https?://[^\s]+)\)` ).FindAllStringSubmatch (string (body ), - 1 )
185218
186219 // Download each referenced file if it hasn't been visited before
@@ -208,3 +241,21 @@ func (s *Scrape) parseBody(body []byte) []byte {
208241
209242 return body
210243}
244+
245+ func (s * Scrape ) getAbsoluteURL (inputURL string ) string {
246+ parsedURL , err := url .Parse (inputURL )
247+ if err != nil {
248+ return ""
249+ }
250+
251+ if parsedURL .IsAbs () {
252+ return inputURL
253+ }
254+
255+ baseURL , err := url .Parse (s .domain )
256+ if err != nil {
257+ return ""
258+ }
259+
260+ return baseURL .ResolveReference (parsedURL ).String ()
261+ }
0 commit comments