我的代码:
func getSourceUrl(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
fmt.Println("Error getSourceUrl: ")
return "", err
}
defer resp.Body.Close()
body := resp.Body
// time = 0
sourcePage, err := ioutil.ReadAll(body)
// time > 5 minutes
return string(sourcePage), err
}
我有一个网站链接,其中包含> 100000行。使用ioutil.ReadAll让我变得非常长(1个链接大约5分钟)。有没有办法让Source网站更快?谢谢!
答案 0 :(得分:1)
@Minato尝试此代码,使用<ul>
<li><a class="navi">One link</a></li>
<li><a class="navi">Second link</a></li>
</ul>
限制参数进行播放。如果你得到太多错误(减少它),请使用它。
M
每次传输变化约为10-40KByte / sec,所有301个文件的最终总数为928MB,11.1分钟为1425 KByte / sec。我相信你应该能够得到类似的结果。
package main
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"runtime"
"time"
)
// Token is an empty struct for signalling
type Token struct{}
// N files to get
var N = 301 // at the source 00000 - 00300
// M max go routines
var M = runtime.NumCPU() * 16
// Throttle to max M go routines
var Throttle = make(chan Token, M)
// DoneStatus is used to signal end of
type DoneStatus struct {
length int
sequence string
duration float64
err error
}
// ExitOK is simple exit counter
var ExitOK = make(chan DoneStatus)
// TotalBytes read
var TotalBytes = 0
// TotalErrors captured
var TotalErrors = 0
// URLTempl is templte for URL construction
var URLTempl = "https://virusshare.com/hashes/VirusShare_%05d.md5"
func close(c io.Closer) {
err := c.Close()
if err != nil {
log.Fatal(err)
}
}
func main() {
log.Printf("start main. M=%d\n", M)
startTime := time.Now()
for i := 0; i < N; i++ {
go func(idx int) {
// slow ramp up fire getData after i seconds
time.Sleep(time.Duration(i) * time.Second)
url := fmt.Sprintf(URLTempl, idx)
_, _ = getData(url) // errors captured as data
}(i)
}
// Count N byte count signals
for i := 0; i < N; i++ {
status := <-ExitOK
TotalBytes += status.length
if status.err != nil {
TotalErrors++
log.Printf("[%d] : %v\n", i, status.err)
continue
}
log.Printf("[%d] file %s, %.1f MByte, %.1f min, %.1f KByte/sec\n",
i, status.sequence,
float64(status.length)/(1024*1024),
status.duration/60,
float64(status.length)/(1024)/status.duration)
}
// totals
duration := time.Since(startTime).Seconds()
log.Printf("Totals: %.1f MByte, %.1f min, %.1f KByte/sec\n",
float64(TotalBytes)/(1024*1024),
duration/60,
float64(TotalBytes)/(1024)/duration)
// using fatal to verify only one go routine is running at the end
log.Fatalf("TotalErrors: %d\n", TotalErrors)
}
func getData(url string) (data []byte, err error) {
var startTime time.Time
defer func() {
// release token
<-Throttle
// signal end of go routine, with some status info
ExitOK <- DoneStatus{
len(data),
url[41:46],
time.Since(startTime).Seconds(),
err,
}
}()
// acquire one of M tokens
Throttle <- Token{}
log.Printf("Started file: %s\n", url[41:46])
startTime = time.Now()
resp, err := http.Get(url)
if err != nil {
return
}
defer close(resp.Body)
data, err = ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return
}
同样尝试http://www.dslreports.com/speedtest/转到设置并选择一堆美国服务器进行测试并将持续时间设置为60秒。这将告诉您实际有效总费率是多少美元。
祝你好运!答案 1 :(得分:0)
您可以一次迭代响应的各个部分,例如;
responseSection := make([]byte, 128)
body.Read(responseSection)
return string(responseSection), err
一次读取128个字节。但是会建议确认下载速度不会导致负载缓慢。
答案 2 :(得分:0)
5分钟可能是网络时间。 也就是说,您通常不希望在内存中缓冲大量对象。 resp.Body是一名读者。 因此,您可以使用io.Copy将其内容复制到文件中。 将sourcePage转换为字符串是一个坏主意,因为它会强制进行另一次分配。