2019年1月13日日曜日

開発環境

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES) (Alan A.A. Donovan(著)、Brian W. Kernighan(著)、柴田 芳樹(翻訳)、丸善出版)の第1章(チュートリアル)、1.6(URLからの並行な取得)、練習問題1.11の解答を求めてみる。

alexa.comにあるトップサイトのurl(aタグのhref)の取得にはPythonとパッケージ、requestsとBeautifulSoupを使用。

コード

sample11.go

package main

import (
 "fmt"
 "io"
 "io/ioutil"
 "net/http"
 "os"
 "strings"
 "time"
)

func main() {
 start := time.Now()
 ch := make(chan string)
 for _, url := range os.Args[2:] {
  if !(strings.HasPrefix(url, "http://") ||
   strings.HasPrefix(url, "https://")) {
   url = "http://" + url
  }
  go fetch(url, ch)
 }
 for range os.Args[2:] {
  fmt.Println(<-ch)
 }
 fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())
}

func fetch(url string, ch chan<- string) {
 start := time.Now()
 resp, err := http.Get(url)
 if err != nil {
  ch <- fmt.Sprint(err)
  return
 }
 nbytes, err := io.Copy(ioutil.Discard, resp.Body)
 resp.Body.Close()
 if err != nil {
  ch <- fmt.Sprintf("while reading %s: %v", url, err)
  return
 }
 secs := time.Since(start).Seconds()
 ch <- fmt.Sprintf("%.2fs %7d %s", secs, nbytes, url)
}

Python 3

sample11.py

#!/usr/bin/env python3
import os
import requests
import bs4

domain = 'https://www.alexa.com'
html = requests.get('https://www.alexa.com/topsites').text
bs_obj = bs4.BeautifulSoup(html, features='lxml')
a_tags = bs_obj.find_all('a')
urls = []
for link in a_tags:
    href = link.get('href')
    if href is not None and href.find('/siteinfo/') != -1:
        url = href[href.rfind('/') + 1:]
        urls.append(url)

os.execl('./fetchall', *urls)

入出力結果(Terminal, cmd(コマンドプロンプト), Jupyter(IPython))

$ go build -o fetchall sample11.go
$ ./sample11.py
0.30s      81 http://baidu.com
0.37s   13252 http://google.co.in
0.39s  101997 http://bing.com
0.41s   12947 http://google.com.hk
0.44s   18906 http://yahoo.co.jp
0.53s    3180 http://t.co
0.57s  182742 http://twitter.com
0.64s    1064 http://reddit.com
0.71s   44329 http://msn.com
0.87s  117147 http://jd.com
0.93s   47708 http://linkedin.com
0.97s   91956 http://ebay.com
1.05s  633944 http://facebook.com
1.16s  237403 http://qq.com
1.25s    3592 http://live.com
1.27s  571629 http://sina.com.cn
1.36s  209047 http://sohu.com
1.38s   11365 http://google.co.jp
1.47s   27942 http://instagram.com
1.50s   78711 http://twitch.tv
1.51s   94478 http://blogspot.com
1.52s  457496 http://amazon.co.jp
1.60s  377433 http://pornhub.com
1.61s  196472 http://livejasmin.com
1.64s  169416 http://microsoft.com
1.67s   80442 http://netflix.com
1.82s   46660 http://csdn.net
1.94s 1338335 http://porn555.com
1.97s   94474 http://weibo.com
1.97s  174695 http://naver.com
2.02s    6400 http://amazon.com
2.09s   83448 http://wikipedia.org
2.09s  227464 http://tribunnews.com
2.11s  243690 http://taobao.com
2.12s  527425 http://yahoo.com
2.17s  199186 http://imdb.com
2.18s   79914 http://github.com
2.29s   75347 http://360.cn
2.32s  247120 http://tmall.com
2.42s   37290 http://aliexpress.com
2.54s   21638 http://alipay.com
2.58s  285497 http://mail.ru
2.70s   13899 http://login.tmall.com
3.04s    9367 http://vk.com
3.51s  114805 http://xvideos.com
3.69s   98597 http://yandex.ru
6.09s   37628 http://pages.tmall.com
Get http://microsoftonline.com: dial tcp 40.84.199.233:80: i/o timeout
30.00s elapsed
$ echo $?
0
$

ということで、あるウェブサイト(この場合はhttp://microsoftonline.com)が応答しない場合の振る舞いは、fetch関数の一つ目のif文で真になりエラーメッセージ(Get http://microsoftonline.com: dial tcp 40.84.199.233:80: i/o timeout)が出力される。ゴールーチンとチャンネルをしようした場合、最後にメッセージが出力されていて、待たずに応答があって取得できたものから出力されているから、並行に処理されていることが分かる。

0 コメント:

コメントを投稿