成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Go 爬蟲之 HTTP 請求 QuickStart

antyiwei / 1658人閱讀

摘要:即是發(fā)送請求的客戶端,請求的執(zhí)行都是由發(fā)起。響應(yīng)信息執(zhí)行請求成功,如何查看響應(yīng)信息。提交文件文件提交應(yīng)該是請求中較為復(fù)雜的內(nèi)容了。主要涉及兩部分內(nèi)容,即讀取響應(yīng)的與設(shè)置請求的。的包中請求是不重定向的,但測試結(jié)果顯示的是自動重定向的。

前幾天在 "知乎想法" 談到了一個話題,如何模仿學(xué)習(xí),舉了通過 net/http client 模仿 Pyhton 的requests的例子。但并未實(shí)踐,難道想法真的只能是想法嗎?當(dāng)然不是,于是我決定先暫停一周 GO 筆記,來實(shí)踐下自己的想法。

有些新的知識,我們可以通過模仿學(xué)習(xí)

本文將通過 GO 實(shí)現(xiàn) requests 的 quick start 文檔中的所有例子,系統(tǒng)學(xué)習(xí)http client的使用。雖然標(biāo)題是 quick start,但其實(shí)內(nèi)容挺多的。

快速體驗

首先,我們來發(fā)起一個 GET 請求,代碼非常簡單。如下:

func get() {
    r, err := http.Get("https://api.github.com/events")
    if err != nil {
        panic(err)
    }
    defer func() { _ = r.Body.Close() }()

    body, _ := ioutil.ReadAll(r.Body)
    fmt.Printf("%s", body)
}

通過 http.Get 方法,獲取到了一個 Response 和一個 error ,即 r 和 err。通過 r 我們能獲取響應(yīng)的信息,err 可以實(shí)現(xiàn)錯誤檢查。

r.Body 被讀取后需要關(guān)閉,可以defer來做這件事。內(nèi)容的讀取可通過 ioutil.ReadAll實(shí)現(xiàn)。

請求方法

除了GET,HTTP還有其他一系列方法,包括POST、PUT、DELETE、HEAD、OPTIONS。快速體驗中的GET是通過一種便捷的方式實(shí)現(xiàn)的,它隱藏了很多細(xì)節(jié)。這里暫時先不用它。

我們先來介紹通用的方法,以幫我們實(shí)現(xiàn)所有HTTP方法的請求。主要涉及兩個重要的類型,Client 和 Request。

Client 即是發(fā)送 HTTP 請求的客戶端,請求的執(zhí)行都是由 Client 發(fā)起。它提供了一些便利的請求方法,比如我們要發(fā)起一個Get請求,可通過 client.Get(url) 實(shí)現(xiàn)。更通用的方式是通過 client.Do(req) 實(shí)現(xiàn),req 屬于 Request 類型。

Request 是用來描述請求信息的結(jié)構(gòu)體,比如請求方法、地址、頭部等信息,我們都可以通過它來設(shè)置。Request 的創(chuàng)建可以通過 http.NewRequest 實(shí)現(xiàn)。

接下來列舉 HTTP 所有方法的實(shí)現(xiàn)代碼。

GET

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodGet, "https://api.github.com/events", nil))

POST

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodPost, "http://httpbin.org/post", nil))

PUT

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodPut, "http://httpbin.org/put", nil))

DELETE

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodDelete, "http://httpbin.org/delete", nil))

HEAD

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodHead, "http://httpbin.org/get", nil))

OPTIONS

r, err := http.DefaultClient.Do(
    http.NewRequest(http.MethodOptions, "http://httpbin.org/get", nil))

上面展示了HTTP所有方法的實(shí)現(xiàn)。這里還幾點(diǎn)需要說明。

DefaultClient,它是 net/http 包提供了默認(rèn)客戶端,一般的請求我們無需創(chuàng)建新的 Client,使用默認(rèn)即可。

GET、POST 和 HEAD 的請求,GO提供了更便捷的實(shí)現(xiàn)方式,Request 不用手動創(chuàng)建。

示例代碼,每個 HTTP 請求方法都有兩種實(shí)現(xiàn)。

GET

r, err := http.DefaultClient.Get("http://httpbin.org/get")
r, err := http.Get("http://httpbin.org/get")

POST

bodyJson, _ := json.Marshal(map[string]interface{}{
    "key": "value",
})
r, err := http.DefaultClient.Post(
    "http://httpbin.org/post",
    "application/json",
    strings.NewReader(string(bodyJson)),
)
r, err := http.Post(
    "http://httpbin.org/post",
    "application/json",
    strings.NewReader(string(bodyJson)),
)

這里順便演示了如何向 POST 接口提交 JSON 數(shù)據(jù)的方式,主要 content-type 的設(shè)置,一般JSON接口的 content-type 為 application/json。

HEAD

r, err := http.DefaultClient.Head("http://httpbin.org/get")
r, err := http.Head("http://httpbin.org/get")

如果看了源碼,你會發(fā)現(xiàn),http.Get 中調(diào)用就是 http.DefaultClient.Get,是同一個意思,只是為了方便,提供這種調(diào)用方法。Head 和 Post 也是如此。

URL參數(shù)

通過將鍵/值對置于 URL 中,我們可以實(shí)現(xiàn)向特定地址傳遞數(shù)據(jù)。該鍵/值將跟在一個問號的后面,例如 http://httpbin.org/get?key=val。 手工構(gòu)建 URL 會比較麻煩,我們可以通過 net/http 提供的方法來實(shí)現(xiàn)。

舉個栗子,比如你想傳遞 key1=value1 和 key2=value2 到 http://httpbin.org/get。代碼如下:

req, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
if err != nil {
    panic(err)
}

params := make(url.Values)
params.Add("key1", "value1")
params.Add("key2", "value2")

req.URL.RawQuery = params.Encode()

// URL 的具體情況 http://httpbin.org/get?key1=value1&key2=value2
// fmt.Println(req.URL.String()) 

r, err := http.DefaultClient.Do(req)

url.Values 可以幫助組織 QueryString,查看源碼發(fā)現(xiàn) url.Values 其實(shí)是 map[string][]string。調(diào)用 Encode 方法,將組織的字符串傳遞給請求 req 的 RawQuery。通過 url.Values也可以設(shè)置一個數(shù)組參數(shù),類似如下的形式:

http://httpbin.org/get?key1=v...

怎么做呢?

params := make(url.Values)
params.Add("key1", "value1")
params.Add("key2", "value2")
params.Add("key2", "value3")

觀察最后一行代碼。其實(shí),只要在 key2 上再增加一個值就可以了。

響應(yīng)信息

執(zhí)行請求成功,如何查看響應(yīng)信息。要查看響應(yīng)信息,可以大概了解下,響應(yīng)通常哪些內(nèi)容?常見的有主體內(nèi)容(Body)、狀態(tài)信息(Status)、響應(yīng)頭部(Header)、內(nèi)容編碼(Encoding)等。

Body

其實(shí),在最開始的時候已經(jīng)演示Body讀取的過程。響應(yīng)內(nèi)容的讀取可通過 ioutil 實(shí)現(xiàn)。

body, err := ioutil.ReadAll(r.Body)

響應(yīng)內(nèi)容多樣,如果是 json,可以直接使用 json.Unmarshal 進(jìn)行解碼,JSON知識不介紹了。

r.Body 實(shí)現(xiàn)了 io.ReadeCloser 接口,為減少資源浪費(fèi)要及時釋放,可以通過 defer 實(shí)現(xiàn)。

defer func() { _ = r.Body.Close() }()
StatusCode

響應(yīng)信息中,除了 Body 主體內(nèi)容,還有其他信息,比如 status code 和 charset 等。

r.StatusCode
r.Status

r.StatusCode 是 HTTP 返回碼,Status 是返回狀態(tài)描述。

Header

響應(yīng)頭信息通過 Response.Header 即可獲取,要說明的一點(diǎn)是,響應(yīng)頭的 Key 是不區(qū)分大小寫。

r.Header.Get("content-type")
r.Header.Get("Content-Type")

你會發(fā)現(xiàn) content-type 和 Content-Type 獲取的內(nèi)容是完全一樣的。

Encoding

如何識別響應(yīng)內(nèi)容編碼呢?我們需要借助 http://golang.org/x/net/html/... 包實(shí)現(xiàn)。先來定義一個函數(shù),代碼如下:

func determineEncoding(r *bufio.Reader) encoding.Encoding {
    bytes, err := r.Peek(1024)
    if err != nil {
        fmt.Printf("err %v", err)
        return unicode.UTF8
    }

    e, _, _ := charset.DetermineEncoding(bytes, "")

    return e
}

怎么調(diào)用它?

bodyReader := bufio.NewReader(r.Body)
e := determineEncoding(bodyReader)
fmt.Printf("Encoding %v
", e)

decodeReader := transform.NewReader(bodyReader, e.NewDecoder())

利用 bufio 生成新的 reader,然后利用 determineEncoding 檢測內(nèi)容編碼,并通過 transform 進(jìn)行編碼轉(zhuǎn)化。

圖片下載

如果訪問內(nèi)容是一張圖片,我們?nèi)绾伟阉螺d下來呢?比如如下地址的圖片。

https://pic2.zhimg.com/v2-5e8...

其實(shí)很簡單,只需要創(chuàng)建新的文件并把響應(yīng)內(nèi)容保存進(jìn)去即可。

f, err := os.Create("as.jpg")
if err != nil {
    panic(err)
}
defer func() { _ = f.Close() }()

_, err = io.Copy(f, r.Body)
if err != nil {
    panic(err)
}

r 即 Response,利用 os 創(chuàng)建了新的文件,然后再通過 io.Copy 將響應(yīng)的內(nèi)容保存進(jìn)文件中。

定制請求頭

如何為請求定制請求頭呢?Request 其實(shí)已經(jīng)提供了相應(yīng)的方法,通過 req.Header.Add 即可完成。

舉個例子,假設(shè)我們將要訪問 http://httpbin.org/get,但這個地址針對 user-agent 設(shè)置了發(fā)爬策略。我們需要修改默認(rèn)的 user-agent。

示例代碼:

req, err := http.NewRequest(http.MethodGet, "http://httpbin.org/get", nil)
if err != nil {
    panic(err)
}

req.Header.Add("user-agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_0)")

如上便可完成任務(wù)。

復(fù)雜的POST請求

前面已經(jīng)展示過了向 POST 接口提交 JSON 數(shù)據(jù)的方式。接下來介紹下另外幾種向 POST 接口提交數(shù)據(jù)的方式,即表單提交和文件提交。

表單提交

表單提交是一個很常用的功能,故而在 net/http 中,除了提供標(biāo)準(zhǔn)的用法外,還給我們提供了簡化的方法。

我們先來介紹個標(biāo)準(zhǔn)的實(shí)現(xiàn)方法。

舉個例子,假設(shè)要向 http://httpbin.org/post 提交 name 為 poloxue 和 password 為 123456 的表單。

payload := make(url.Values)
payload.Add("name", "poloxue")
payload.Add("password", "123456")
req, err := http.NewRequest(
    http.MethodPost,
    "http://httpbin.org/post",
    strings.NewReader(payload.Encode()),
)
if err != nil {
    panic(err)
}
req.Header.Add("Content-Type", "application/x-www-form-urlencoded")

r, err := http.DefaultClient.Do(req)

POST 的 payload 是形如 name=poloxue&password=123456 的字符串,故而我們可以通過 url.Values 進(jìn)行組織。

提交給 NewRequest 的內(nèi)容必須是實(shí)現(xiàn) Reader 接口的類型,所以需要 strings.NewReader轉(zhuǎn)化下。

Form 表單提交的 content-type 要是 application/x-www-form-urlencoded,也要設(shè)置下。

復(fù)雜的方式介紹完了。接著再介紹簡化的方式,其實(shí)表單提交只需調(diào)用 http.PostForm 即可完成。示例代碼如下:

payload := make(url.Values)
payload.Add("name", "poloxue")
payload.Add("password", "123456")
r, err := http.PostForm("http://httpbin.org/post", form)

竟是如此的簡單。

提交文件

文件提交應(yīng)該是 HTTP 請求中較為復(fù)雜的內(nèi)容了。其實(shí)說難也不難,區(qū)別于其他的請求,我們要花些精力來讀取文件,組織提交POST的數(shù)據(jù)。

舉個例子,假設(shè)現(xiàn)在我有一個圖片文件,名為 as.jpg,路徑在 /Users/polo 目錄下?,F(xiàn)在要將這個圖片提交給 http://httpbin.org/post。

我們要先組織 POST 提交的內(nèi)容,代碼如下:

filename := "/Users/polo/as.jpg"

f, err := os.Open(filename)
if err != nil {
    panic(err)
}
defer func() { _ = f.Close() }()

uploadBody := &bytes.Buffer{}
writer := multipart.NewWriter(uploadBody)

fWriter, err := writer.CreateFormFile("uploadFile", filename)
if err != nil {
    fmt.Printf("copy file writer %v", err)
}

_, err = io.Copy(fWriter, f)
if err != nil {
    panic(err)
}

fieldMap := map[string]string{
    "filename": filename,
}
for k, v := range fieldMap {
    _ = writer.WriteField(k, v)
}

err = writer.Close()
if err != nil {
    panic(err)
}

我認(rèn)為,數(shù)據(jù)組織分為幾步完成,如下:

第一步,打開將要上傳的文件,使用 defer f.Close() 做好資源釋放的準(zhǔn)備;

第二步,創(chuàng)建存儲上傳內(nèi)容的 bytes.Buffer,變量名為 uploadBody;

第三步,通過 multipart.NewWriter 創(chuàng)建 writer,用于向 buffer中寫入文件提供的內(nèi)容;

第四步,通過writer.CreateFormFile 創(chuàng)建上傳文件并通過 io.Copy 向其中寫入內(nèi)容;

最后,通過 writer.WriteField 添加其他的附加信息,注意最后要把 writer 關(guān)閉;

至此,文件上傳的數(shù)據(jù)就組織完成了。接下來,只需調(diào)用 http.Post 方法即可完成文件上傳。

r, err := http.Post("http://httpbin.org/post", writer.FormDataContentType(), uploadBody)

有一點(diǎn)要注意,請求的content-type需要設(shè)置,而通過 writer.FormDataContentType() 即能獲得上傳文件的類型。

到此,文件提交也完成了,不知道有沒有非常簡單的感覺。

Cookie

主要涉及兩部分內(nèi)容,即讀取響應(yīng)的 cookie 與設(shè)置請求的 cookie。響應(yīng)的 cookie 獲取方式非常簡單,直接調(diào)用 r.Cookies 即可。

重點(diǎn)來說說,如何設(shè)置請求 cookie。cookie設(shè)置有兩種方式,一種設(shè)置在 Client 上,另一種是設(shè)置在 Request 上。

Client 上設(shè)置 Cookie

直接看示例代碼:

cookies := make([]*http.Cookie, 0)

cookies = append(cookies, &http.Cookie{
    Name:   "name",
    Value:  "poloxue",
    Domain: "httpbin.org",
    Path:   "/cookies",
})
cookies = append(cookies, &http.Cookie{
    Name:   "id",
    Value:  "10000",
    Domain: "httpbin.org",
    Path:   "/elsewhere",
})

url, err := url.Parse("http://httpbin.org/cookies")
if err != nil {
    panic(err)
}

jar, err := cookiejar.New(nil)
if err != nil {
    panic(err)
}
jar.SetCookies(url, cookies)

client := http.Client{Jar: jar}

r, err := client.Get("http://httpbin.org/cookies")

代碼中,我們首先創(chuàng)建了 http.Cookie 切片,然后向其中添加了 2 個 Cookie 數(shù)據(jù)。這里通過 cookiejar,保存了 2 個新建的 cookie。

這次我們不能再使用默認(rèn)的 DefaultClient 了,而是要創(chuàng)建新的 Client,并將保存 cookie 信息的 cookiejar 與 client 綁定。接下里,只需要使用新創(chuàng)建的 Client 發(fā)起請求即可。

請求上設(shè)置 Cookie

請求上的 cookie 設(shè)置,通過 req.AddCookie即可實(shí)現(xiàn)。示例代碼:

req, err := http.NewRequest(http.MethodGet, "http://httpbin.org/cookies", nil)
if err != nil {
    panic(err)
}

req.AddCookie(&http.Cookie{
    Name:   "name",
    Value:  "poloxue",
    Domain: "httpbin.org",
    Path:   "/cookies",
})

r, err := http.DefaultClient.Do(req)

挺簡單的,沒什么要介紹的。

cookie 設(shè)置 Client 和 設(shè)置在 Request 上有何區(qū)別?一個最易想到的區(qū)別就是,Request 的 cookie 只是當(dāng)次請求失效,而 Client 上的 cookie 是隨時有效的,只要你用的是這個新創(chuàng)建的 Client。

重定向和請求歷史

默認(rèn)情況下,所有類型請求都會自動處理重定向。

Python 的 requests 包中 HEAD 請求是不重定向的,但測試結(jié)果顯示 net/http 的 HEAD 是自動重定向的。

net/http 中的重定向控制可以通過 Client 中的一個名為 CheckRedirect 的成員控制,它是函數(shù)類型。定義如下:

type Client struct {
    ...
    CheckRedirect func(req *Request, via []*Request) error
    ...
}

接下來,我們來看看怎么使用。

假設(shè)我們要實(shí)現(xiàn)的功能:為防止發(fā)生循環(huán)重定向,重定向次數(shù)定義不能超過 10 次,而且要記錄歷史 Response。

示例代碼:

var r *http.Response
history := make([]*http.Response, 0)

client := http.Client{
    CheckRedirect: func(req *http.Request, hrs []*http.Request) error {
        if len(hrs) >= 10 {
            return errors.New("redirect to many times")
        }

        history = append(history, req.Response)
        return nil
    },
}

r, err := client.Get("http://github.com")

首先創(chuàng)建了 http.Response 切片的變量,名稱為 history。接著在 http.Client 中為 CheckRedirect 賦予一個匿名函數(shù),用于控制重定向的行為。CheckRedirect 函數(shù)的第一個參數(shù)表示下次將要請求的 Request,第二個參數(shù)表示已經(jīng)請求過的 Request。

當(dāng)發(fā)生重定向時,當(dāng)前的 Request 會保存上次請求的 Response,故而此處可以將 req.Response 追加到 history 變量中。

超時設(shè)置

Request 發(fā)出后,如果服務(wù)端遲遲沒有響應(yīng),那豈不是很尷尬。那么我們就會想,能否為請求設(shè)置超時規(guī)則呢?毫無疑問,當(dāng)然可以。

超時可以分為連接超時和響應(yīng)讀取超時,這些都可以設(shè)置。但正常情況下,并不想有那么明確的區(qū)別,那么也可以設(shè)置個總超時。

總超時

總的超時時間的設(shè)置是綁定在 Client 的一個名為 Timeout 的成員之上,Timeout 是 time.Duration。

假設(shè)這是超時時間為 10 秒,示例代碼:

client := http.Client{
    Timeout:   time.Duration(10 * time.Second),
}
連接超時

連接超時可通過 Client 中的 Transport 實(shí)現(xiàn)。Transport 中有個名為 Dial 的成員函數(shù),可用設(shè)置連接超時。Transport 是 HTTP 底層的數(shù)據(jù)運(yùn)輸者。

假設(shè)設(shè)置連接超時時間為 2 秒,示例代碼:

t := &http.Transport{
    Dial: func(network, addr string) (net.Conn, error) {
        timeout := time.Duration(2 * time.Second)
        return net.DialTimeout(network, addr, timeout)
    },
}

在 Dial 的函數(shù)中,我們通過 net.DialTimeout 進(jìn)行網(wǎng)絡(luò)連接,實(shí)現(xiàn)了連接超時功能。

讀取超時

讀取超時也要通過 Client 的 Transport 設(shè)置,比如設(shè)置響應(yīng)的讀取為 8 秒。

示例代碼:

t := &http.Transport{
    ResponseHeaderTimeout: time.Second * 8,
}
綜合所有,Client 的創(chuàng)建代碼如下:

t := &http.Transport{
    Dial: func(network, addr string) (net.Conn, error) {
        timeout := time.Duration(2 * time.Second)
        return net.DialTimeout(network, addr, timeout)
    },
    ResponseHeaderTimeout: time.Second * 8,
}
client := http.Client{
    Transport: t,
    Timeout:   time.Duration(10 * time.Second),
}

除了上面的幾個超時設(shè)置,Transport 還有其他一些關(guān)于超時的設(shè)置,可以看下 Transport 的定義,還有發(fā)現(xiàn)三個與超時相關(guān)的定義:

// IdleConnTimeout is the maximum amount of time an idle
// (keep-alive) connection will remain idle before closing
// itself.
// Zero means no limit.
IdleConnTimeout time.Duration

// ResponseHeaderTimeout, if non-zero, specifies the amount of
// time to wait for a server"s response headers after fully
// writing the request (including its body, if any). This
// time does not include the time to read the response body.
ResponseHeaderTimeout time.Duration

// ExpectContinueTimeout, if non-zero, specifies the amount of
// time to wait for a server"s first response headers after fully
// writing the request headers if the request has an
// "Expect: 100-continue" header. Zero means no timeout and
// causes the body to be sent immediately, without
// waiting for the server to approve.
// This time does not include the time to send the request header.
ExpectContinueTimeout time.Duration

分別是 IdleConnTimeout (連接空閑超時時間,keep-live 開啟)、TLSHandshakeTimeout (TLS 握手時間)和 ExpectContinueTimeout(似乎已含在 ResponseHeaderTimeout 中了,看注釋)。

到此,完成了超時的設(shè)置。相對于 Python requests 確實(shí)是復(fù)雜很多。

請求代理

代理還是挺重要的,特別對于開發(fā)爬蟲的同學(xué)。那 net/http 怎么設(shè)置代理?這個工作還是要依賴 Client 的成員 Transport 實(shí)現(xiàn),這個 Transport 還是挺重要的。

Transport 有個名為 Proxy 的成員,具體看看怎么使用吧。假設(shè)我們要通過設(shè)置代理來請求谷歌的主頁,代理地址為 http://127.0.0.1:8087。

示例代碼:

proxyUrl, err := url.Parse("http://127.0.0.1:8087")
if err != nil {
    panic(err)
}
t := &http.Transport{
    Proxy:           http.ProxyURL(proxyUrl),
    TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
client := http.Client{
    Transport: t,
    Timeout:   time.Duration(10 * time.Second),
}

r, err := client.Get("https://google.com")

主要關(guān)注 http.Transport 創(chuàng)建的代碼。兩個參數(shù),分時 Proxy 和 TLSClientConfig,分別用于設(shè)置代理和禁用 https 驗證。我發(fā)現(xiàn)其實(shí)不設(shè)置 TLSClientConfig 也可以請求成功,具體原因沒仔細(xì)研究。

錯誤處理

錯誤處理其實(shí)都不用怎么介紹,GO中的一般錯誤主要是檢查返回的error,HTTP 請求也是如此,它會視情況返回相應(yīng)錯誤信息,比如超時、網(wǎng)絡(luò)連接失敗等。

示例代碼中的錯誤都是通過 panic 拋出去的,真實(shí)的項目肯定不是這樣的,我們需要記錄相關(guān)日志,時刻做好錯誤恢復(fù)工作。

總結(jié)

本文以 Python 的 requests 文檔為指導(dǎo)方向,整理了 requests 快速入門文檔中的案例在 GO 的是如何實(shí)現(xiàn)的。要說明的是, GO 其實(shí)也提供了對應(yīng)于 requests 的克隆版本,[github地址](
https://github.com/levigross/...。暫時我也還沒有看,有興趣的朋友可以去研究一下。

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/45252.html

相關(guān)文章

  • 爬蟲requests模塊 入門到入獄 :基礎(chǔ)知識+實(shí)戰(zhàn)分析

    ?????? ???Hello,大家好我叫是Dream呀,一個有趣的Python博主,小白一枚,多多關(guān)照??? ???CSDN Python領(lǐng)域新星創(chuàng)作者,大二在讀,歡迎大家找我合作學(xué)習(xí) ?入門須知:這片樂園從不缺乏天才,努力才是你的最終入場券!??? ?最后,愿我們都能在看不到的地方閃閃發(fā)光,一起加油進(jìn)步??? ???一萬次悲傷,依然會有Dream,我一直在最溫暖的地方等你,唱的就是我!哈哈哈~...

    yagami 評論0 收藏0
  • Pyspider框架 —— Python爬蟲實(shí)戰(zhàn)爬取 V2EX 網(wǎng)站帖子

    摘要:背景一個國人編寫的強(qiáng)大的網(wǎng)絡(luò)爬蟲系統(tǒng)并帶有強(qiáng)大的??蚣軐W(xué)習(xí)時走過的一些坑錯誤我所遇到的一些錯誤首先,本爬蟲目標(biāo)使用框架爬取網(wǎng)站的帖子中的問題和內(nèi)容,然后將爬取的數(shù)據(jù)保存在本地。修飾器,表示每天會執(zhí)行一次,這樣就能抓到最新的帖子了。 背景: PySpider:一個國人編寫的強(qiáng)大的網(wǎng)絡(luò)爬蟲系統(tǒng)并帶有強(qiáng)大的WebUI。采用Python語言編寫,分布式架構(gòu),支持多種數(shù)據(jù)庫后端,強(qiáng)大的WebUI...

    codecraft 評論0 收藏0
  • Golang實(shí)現(xiàn)簡單爬蟲框架(3)——簡單并發(fā)版

    摘要:在上篇文章實(shí)現(xiàn)簡單爬蟲框架單任務(wù)版爬蟲中我們實(shí)現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。在上篇文章Golang實(shí)現(xiàn)簡單爬蟲框架(2)——單任務(wù)版爬蟲中我們實(shí)現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。整個過程中,獲取網(wǎng)頁數(shù)據(jù)速度比較慢,那么我們就把獲取數(shù)據(jù)模塊做成并發(fā)執(zhí)行。在...

    番茄西紅柿 評論0 收藏0
  • Golang實(shí)現(xiàn)簡單爬蟲框架(3)——簡單并發(fā)版

    摘要:在上篇文章實(shí)現(xiàn)簡單爬蟲框架單任務(wù)版爬蟲中我們實(shí)現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。在上篇文章Golang實(shí)現(xiàn)簡單爬蟲框架(2)——單任務(wù)版爬蟲中我們實(shí)現(xiàn)了一個簡單的單任務(wù)版爬蟲,對于單任務(wù)版爬蟲,每次都要請求頁面,然后解析數(shù)據(jù),然后才能請求下一個頁面。整個過程中,獲取網(wǎng)頁數(shù)據(jù)速度比較慢,那么我們就把獲取數(shù)據(jù)模塊做成并發(fā)執(zhí)行。在...

    lewinlee 評論0 收藏0
  • 用TypeScript開發(fā)爬蟲程序

    摘要:全局安裝目前版本,這個版本不再需要使用命令了?,F(xiàn)在嘗試深入抓取文章內(nèi)容可以發(fā)現(xiàn)因為訪問服務(wù)器太迅猛,導(dǎo)致出現(xiàn)很多次錯誤。解決添加文件修改文件為修改文件為觀察輸出可以看到,程序?qū)崿F(xiàn)了隔一秒再請求下一個內(nèi)容頁。 全局安裝typescript: npm install -g typescript 目前版本2.0.3,這個版本不再需要使用typings命令了。但是vscode捆綁的版本是1....

    CocoaChina 評論0 收藏0

發(fā)表評論

0條評論

antyiwei

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<