Add GetCookies and SetCookies
This commit is contained in:
parent
deb946cf22
commit
f0d7735a76
6 changed files with 97 additions and 7 deletions
26
README.md
26
README.md
|
|
@ -189,6 +189,32 @@ Logout (clear session):
|
||||||
scraper.Logout()
|
scraper.Logout()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If you want save session between restarts, you can save cookies with `scraper.GetCookies()` and restore with `scraper.SetCookies()`.
|
||||||
|
|
||||||
|
For example, save cookies:
|
||||||
|
|
||||||
|
```golang
|
||||||
|
cookies := scraper.GetCookies()
|
||||||
|
// serialize to JSON
|
||||||
|
js, _ := json.Marshal(cookies)
|
||||||
|
// save to file
|
||||||
|
f, _ = os.Create("cookies.json")
|
||||||
|
f.Write(js)
|
||||||
|
```
|
||||||
|
|
||||||
|
and load cookies:
|
||||||
|
|
||||||
|
```golang
|
||||||
|
f, _ := os.Open("cookies.json")
|
||||||
|
// deserialize from JSON
|
||||||
|
var cookies []*http.Cookie
|
||||||
|
json.NewDecoder(f).Decode(&cookies)
|
||||||
|
// load cookies
|
||||||
|
scraper.SetCookies(cookies)
|
||||||
|
// check login status
|
||||||
|
scraper.IsLoggedIn()
|
||||||
|
```
|
||||||
|
|
||||||
### Use Proxy
|
### Use Proxy
|
||||||
|
|
||||||
Support HTTP(s) and SOCKS5 proxy
|
Support HTTP(s) and SOCKS5 proxy
|
||||||
|
|
|
||||||
4
api.go
4
api.go
|
|
@ -23,15 +23,17 @@ func (s *Scraper) RequestAPI(req *http.Request, target interface{}) error {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !s.isLogged {
|
||||||
if !s.IsGuestToken() || s.guestCreatedAt.Before(time.Now().Add(-time.Hour*3)) {
|
if !s.IsGuestToken() || s.guestCreatedAt.Before(time.Now().Add(-time.Hour*3)) {
|
||||||
err := s.GetGuestToken()
|
err := s.GetGuestToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
req.Header.Set("X-Guest-Token", s.guestToken)
|
||||||
|
}
|
||||||
|
|
||||||
req.Header.Set("Authorization", "Bearer "+s.bearerToken)
|
req.Header.Set("Authorization", "Bearer "+s.bearerToken)
|
||||||
req.Header.Set("X-Guest-Token", s.guestToken)
|
|
||||||
|
|
||||||
for _, cookie := range s.client.Jar.Cookies(req.URL) {
|
for _, cookie := range s.client.Jar.Cookies(req.URL) {
|
||||||
if cookie.Name == "ct0" {
|
if cookie.Name == "ct0" {
|
||||||
|
|
|
||||||
20
auth.go
20
auth.go
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/cookiejar"
|
"net/http/cookiejar"
|
||||||
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -73,6 +74,8 @@ func (s *Scraper) getFlowToken(data map[string]interface{}) (string, error) {
|
||||||
|
|
||||||
// IsLoggedIn check if scraper logged in
|
// IsLoggedIn check if scraper logged in
|
||||||
func (s *Scraper) IsLoggedIn() bool {
|
func (s *Scraper) IsLoggedIn() bool {
|
||||||
|
s.isLogged = true
|
||||||
|
s.setBearerToken(bearerToken2)
|
||||||
req, err := http.NewRequest("GET", "https://api.twitter.com/1.1/account/verify_credentials.json", nil)
|
req, err := http.NewRequest("GET", "https://api.twitter.com/1.1/account/verify_credentials.json", nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
|
|
@ -81,6 +84,7 @@ func (s *Scraper) IsLoggedIn() bool {
|
||||||
err = s.RequestAPI(req, &verify)
|
err = s.RequestAPI(req, &verify)
|
||||||
if err != nil || verify.Errors != nil {
|
if err != nil || verify.Errors != nil {
|
||||||
s.isLogged = false
|
s.isLogged = false
|
||||||
|
s.setBearerToken(bearerToken)
|
||||||
} else {
|
} else {
|
||||||
s.isLogged = true
|
s.isLogged = true
|
||||||
}
|
}
|
||||||
|
|
@ -190,3 +194,19 @@ func (s *Scraper) Logout() {
|
||||||
s.client.Jar, _ = cookiejar.New(nil)
|
s.client.Jar, _ = cookiejar.New(nil)
|
||||||
s.setBearerToken(bearerToken)
|
s.setBearerToken(bearerToken)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Scraper) GetCookies() []*http.Cookie {
|
||||||
|
var cookies []*http.Cookie
|
||||||
|
for _, cookie := range s.client.Jar.Cookies(twURL) {
|
||||||
|
if strings.Contains(cookie.Name, "guest") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
cookie.Domain = twURL.Host
|
||||||
|
cookies = append(cookies, cookie)
|
||||||
|
}
|
||||||
|
return cookies
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Scraper) SetCookies(cookies []*http.Cookie) {
|
||||||
|
s.client.Jar.SetCookies(twURL, cookies)
|
||||||
|
}
|
||||||
|
|
|
||||||
33
auth_test.go
Normal file
33
auth_test.go
Normal file
|
|
@ -0,0 +1,33 @@
|
||||||
|
package twitterscraper_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
twitterscraper "github.com/n0madic/twitter-scraper"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
username = os.Getenv("TWITTER_USERNAME")
|
||||||
|
password = os.Getenv("TWITTER_PASSWORD")
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAuth(t *testing.T) {
|
||||||
|
scraper := twitterscraper.New()
|
||||||
|
if err := scraper.Login(username, password); err != nil {
|
||||||
|
t.Fatalf("Login() error = %v", err)
|
||||||
|
}
|
||||||
|
if !scraper.IsLoggedIn() {
|
||||||
|
t.Error("Expected IsLoggedIn() = true")
|
||||||
|
}
|
||||||
|
cookies := scraper.GetCookies()
|
||||||
|
scraper.Logout()
|
||||||
|
if scraper.IsLoggedIn() {
|
||||||
|
t.Error("Expected IsLoggedIn() = false")
|
||||||
|
}
|
||||||
|
scraper2 := twitterscraper.New()
|
||||||
|
scraper2.SetCookies(cookies)
|
||||||
|
if !scraper2.IsLoggedIn() {
|
||||||
|
t.Error("Expected restored IsLoggedIn() = true")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,6 @@ package twitterscraper_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
twitterscraper "github.com/n0madic/twitter-scraper"
|
twitterscraper "github.com/n0madic/twitter-scraper"
|
||||||
|
|
@ -14,7 +13,7 @@ func authSearchScraper() error {
|
||||||
if searchScraper.IsLoggedIn() {
|
if searchScraper.IsLoggedIn() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return searchScraper.Login(os.Getenv("TWITTER_USERNAME"), os.Getenv("TWITTER_PASSWORD"))
|
return searchScraper.Login(username, password)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFetchSearchCursor(t *testing.T) {
|
func TestFetchSearchCursor(t *testing.T) {
|
||||||
|
|
|
||||||
10
util.go
10
util.go
|
|
@ -3,6 +3,7 @@ package twitterscraper
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -12,6 +13,7 @@ var (
|
||||||
reHashtag = regexp.MustCompile(`\B(\#\S+\b)`)
|
reHashtag = regexp.MustCompile(`\B(\#\S+\b)`)
|
||||||
reTwitterURL = regexp.MustCompile(`https:(\/\/t\.co\/([A-Za-z0-9]|[A-Za-z]){10})`)
|
reTwitterURL = regexp.MustCompile(`https:(\/\/t\.co\/([A-Za-z0-9]|[A-Za-z]){10})`)
|
||||||
reUsername = regexp.MustCompile(`\B(\@\S{1,15}\b)`)
|
reUsername = regexp.MustCompile(`\B(\@\S{1,15}\b)`)
|
||||||
|
twURL = urlParse("https://twitter.com")
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *Scraper) newRequest(method string, url string) (*http.Request, error) {
|
func (s *Scraper) newRequest(method string, url string) (*http.Request, error) {
|
||||||
|
|
@ -192,3 +194,11 @@ func stringInSlice(a string, list []string) bool {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func urlParse(u string) *url.URL {
|
||||||
|
parsed, err := url.Parse(u)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return parsed
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue