双六工場日誌

平凡な日常を淡々と綴ります。

MacにTensorFlowを入れようとしたら、Numpyのエラーが出たのでメモ

自分のMac (Mavericks 10.9.5) を入れようとしたら、Numpyのエラーが出て詰まったのでメモ。

TensorFlowは、公式サイトの以下の手順でインストール

[https://www.tensorflow.org/versions/master/get_started/os_setup.html#pip-installation]

sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.7.1-cp27-none-any.whl

上記で、問題なくインストールできたものの、以下のエラーが出てimportできず。

$ python
>>> import tensorflow
(中略)
Error: numpy.core.multiarray failed to import

ググッて調べて見ると、System PythonにTensorFlowを入れると、別PATHのNumpyを読んでしまうためにエラーが出るという情報あり。

https://groups.google.com/a/tensorflow.org/forum/#!topic/discuss/O4JQjcyI-9M

In my case (using mac OS) reinstalling numpy version 1.10 with pip was not enough because pip installs in /Library/Python/2.7/site-packages> I had numpy 1.6 simultaneously in a different location /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python When importing tensorflow this was the location first sought for numpy (you can check that with sys.path). Solution: I had to manually remove numpy from this other location not used by pip with "sudo rm .r numpy". Then just restart python.

ここに書かれていた情報を参考に「/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python」以下を見てみたところ、こちらにも過去に入れたと思われるNumpyのファイルがあったので、とりあえずリネームして動作確認

cd /System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/
sudo mv numpy/ numpy_old
$ python
>>> import tensorflow

こちらで問題なく動いた様子。


以下はエラーログをググった際に引っ掛けるようのエラーログ全文。

>>> import tensorflow as tf
RuntimeError: module compiled against API version 9 but this version of numpy is 6
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Library/Python/2.7/site-packages/tensorflow/__init__.py", line 23, in <module>
    from tensorflow.python import *
  File "/Library/Python/2.7/site-packages/tensorflow/python/__init__.py", line 49, in <module>
    from tensorflow import contrib
  File "/Library/Python/2.7/site-packages/tensorflow/contrib/__init__.py", line 23, in <module>
    from tensorflow.contrib import layers
  File "/Library/Python/2.7/site-packages/tensorflow/contrib/layers/__init__.py", line 68, in <module>
    from tensorflow.contrib.layers.python.layers import *
  File "/Library/Python/2.7/site-packages/tensorflow/contrib/layers/python/layers/__init__.py", line 22, in <module>
    from tensorflow.contrib.layers.python.layers.initializers import *
  File "/Library/Python/2.7/site-packages/tensorflow/contrib/layers/python/layers/initializers.py", line 24, in <module>
    from tensorflow.python.ops import random_ops
  File "/Library/Python/2.7/site-packages/tensorflow/python/ops/random_ops.py", line 23, in <module>
    from tensorflow.python.framework import ops
  File "/Library/Python/2.7/site-packages/tensorflow/python/framework/ops.py", line 39, in <module>
    from tensorflow.python.framework import versions
  File "/Library/Python/2.7/site-packages/tensorflow/python/framework/versions.py", line 22, in <module>
    from tensorflow.python import pywrap_tensorflow
  File "/Library/Python/2.7/site-packages/tensorflow/python/pywrap_tensorflow.py", line 28, in <module>
    _pywrap_tensorflow = swig_import_helper()
  File "/Library/Python/2.7/site-packages/tensorflow/python/pywrap_tensorflow.py", line 24, in swig_import_helper
    _mod = imp.load_module('_pywrap_tensorflow', fp, pathname, description)
ImportError: numpy.core.multiarray failed to import

Python製クローラー「Scrapy」の始め方メモ

下書きのまま半年ぐらいほったらかしだったものからサルベージ。内容が古くなっているかもですがご容赦ください。

Python製クローラー「Scrapy」は、さくっとクローラーをつくる際に非常に便利なんですが、フレームワークの全体像を理解するところで時間がかかったので、クローラーをつくる際のとっかかりのところをメモとしてまとめました。

インストール

まずは、依存パッケージのインストール。以下は、「Amazon Linux AMI 2015.09」の場合。

$ sudo yum groupinstall "Development tools" $ sudo yum install python-devel libffi-devel openssl-devel libxml2-devel libxslt-devel

続いて、本体インストール。service_identityは、MITM攻撃を防ぐためのパッケージで、一緒に入れておくのが推奨とのことなので、最初に入れておきます。System Pythonにそのまま追加する手順になっていますが、virtualenv等で環境を分けている場合は、適宜読み替えてください。

$ sudo pip install scrapy service_identity

雛形の作成

ScrapyのProject雛形をつくる

Scrapyを入れたら、続いてクローラーの雛形を作っていきます。まずは、クローラーや各種設定ファイルを入れるは異なる「プロジェクト」を作成します。"scrapy"コマンドが使えるようになっているはずなので、「scrapy startproject <プロジェクト名>」で、カレントディレクトリにプロジェクトの雛形ができます。

$ scrapy startproject example_project

コマンドが成功すると以下のような雛形ができます。

$ tree example_project/
example_project/
├── example_project
│   ├── __init__.py
│   ├── items.py: 収集対象の項目を定義するファイル
│   ├── pipelines.py: データ収集後のアクションを定義するファイル
│   ├── settings.py: アクセス間隔などのクローラーの設定を行うファイル
│   └── spiders
│       └── __init__.py
└── scrapy.cfg: プロジェクト全体の設定ファイル

プロジェクトの中にクローラーの雛形をつくる

続いて、プロジェクトの中にクローラーの雛形を作ります。クローラーをつくるコマンドは「scrapy genspider -t <Template名> <クローラー名> <収集対象サイトドメイン>」です。

<Template名>は、クローラーのひな形の指定。以下の4つのうちのどれかが指定できますが、Webサイトを順に辿って情報を取得する一般的なクローラーをつくる際には、「crawl」オプションを指定します。

  • basic
  • crawl
  • csvfeed
  • xmlfeed

<クローラー名>は、あとでクローラーを走らせる時に指定する名前です。<収集対象サイトドメイン>は、ひな形の中の"allow_domain"、"start_urls"に利用されるドメイン名です。収集したいサイトのドメイン(URLから"http://"を取ったもの)を指定します。

$ cd example_project $ scrapy genspider -t crawl example-crawler www.example.com

ここまでで終わると以下のような雛形ができます。*1

example_project/
├── example_project
│   ├── __init__.py
│   ├── items.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       ├── __init__.py
│       └── example_crawler.py: クローラーの定義を行うファイル
└── scrapy.cfg

これで作った雛形のうち、以下の3つに具体的な設定を入れることでクローラー完成です。

  • settings.py
  • items.py
  • example_crawler.py

具体的なクローリング設定

収集間隔の設定(settings.py)

最初にやっておくべきなのは、settings.pyでの収集間隔の設定です。

クローラーを動かす際、適切な収集間隔が設定されておらず、休みなくそのサイトにアクセスしてしまうと、そのサービスに迷惑をかけてしまうことになりかねません。そのため、最初に以下をsettings.pyに書き込んで、1秒程度*2の間隔を空けてアクセスするようにします。

DOWNLOAD_DELAY=1

収集対象項目の定義(items.py)

続いて、収集対象項目を設定します。scrapyでは、"scrapy.Item"を継承したクラスで、出力対象項目を定義します。items.pyの雛形を開くと以下のようになっています。

import scrapy

class ExampleProjectItem(scrapy.Item):
     # define the fields for your item here like:
     # name = scrapy.Field()
     pass

ここでは、"name"のコメントを外し、"body"を追加してみます。ここで急にクラスが出てくるところがわかりにくい点だと思いますが、内容がわからずとも、ここに「<項目名> = scrapy.Field()」を追加しておけば、取得対象項目を増やすことができることがわかっていれば十分です。

import scrapy


class ExampleProjectItem(scrapy.Item):
     # define the fields for your item here like:
     name = scrapy.Field()
     body = scrapy.Field()

クローラーの設定(example_crawler.py)

example_crawler.pyは、以下のような中身になっています。「name」のところがクローラー雛形作成時に指定した<クローラー名>となっています。

class ExampleCrawlerSpider(CrawlSpider):
    name = 'example-crawler'
    allowed_domains = ['www.example.com']
    start_urls = ['http://www.www.example.com/']

    rules = (
        Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        i = ExampleProjectItem()
        #i['domain_id'] = response.xpath('//input[@id="sid"]/@value').extract()
        #i['name'] = response.xpath('//div[@id="name"]').extract()
        #i['description'] = response.xpath('//div[@id="description"]').extract()
        return i
  • name: このクローラーの名前。最初につけた名前。
  • allowed_domains: クローリング対象となるドメイン。ここで指定されていないドメインにリンクが貼られていても収集対象にならない。
  • start_urls: クローリングの出発点となるURLのリスト
  • rules: クローリングしたページのうち、リンクを辿るURLとその動作を指定する設定です。
  • parse_item: クローリングしたベージからの情報抽出方法を指定。ページの内容は"response"という変数の中に格納されて渡されるので、その中身を"items.py"で定義したオブジェクトに入れてreturnで返すと、フレームワークがよしなに整形して出力してくれる。*3

こちらの最低限の変更点は、"rules"と"parse_item"メソッドです。

rulesは、ページに含まれるどのリンクを辿るかという設定です。Scrapyは、何も記述せずとも、<a>タグの"href"に書かれているリンク先をすべて取得してきてくれます。その取得したリンクのうち、どれを辿って、どれを辿らないのかを設定するのかをここで決めます。

rules = ( Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True), )

デフォルトの「(allow=r'Items/')」は、収集対象ドメインの中で「items/」が含まれるURLを取得対象にするという意味になります。ここを対象のサイトに合わせて変更してください。

このような自動的にリンクを集めてきてくれるのは非常に便利なのですが、デフォルト動作を変えたい場合、若干ハードルが高いのが悩ましいところ。

parse_itemは、このrulesで引っかかったページデータの処理内容を書くメソッドです。引数「response」には、取得したページのデータが入っています。この取得したデータをitems.pyで定義した取得項目にマッピングします。items.pyでは、「name」と「body」を定義していたので、それとページの内容の対応付けを書き入れます。取得したページの内容はXPATHもしくはCSSのセレクタでの指定が可能です。取得対象を決める際には、取得対象のサイトの構造をChromeのデベロッパーツール等で確認すると便利です。

たとえば、以下のように変更します。そのほか具体的な指定方法は、公式サイトの例が詳しいので、そちら参照で。

def parse_item(self, response):
    i = ExampleProjectItem()
    i['name'] = response.xpath('//div[@id="name"]').extract()
    i['body'] = response.xpath('//body').extract()
    return i

ここまでで、最低限のクローラー作成は完了です。クセさえ掴んでしまえば、ほとんど自分でコードを書くことなくクローラーをつくることができます。

データ収集

作成したクローラーを動かすコマンドは、「scrapy crawl <クローラー名> -o <出力先ファイル名>」です。<クローラー名>はクローラーの雛形作成時に指定したものです。また、出力形式はCSV、JSON、JSONLinesから選択できますが、どの形式を使うかh<出力先ファイル名>に指定する、ファイルの拡張子から自動的に選択されます。

たとえば、以下のように拡張子「.jl」を使うと、JSONLinesでの出力となり、各ページが1行のJSONに対応する形でファイルにクローリング結果が書き込まれます。

$ scrapy crawl example_crawler -o output.jl

クローラーを作っていく際には、この出力結果と実際のサイトを比較して、items.pyとparse_itemsに必要なフィールドを足し引きしていくことになります。

まとめ

Scrapyでクローリングを始めるに当たって、最低限必要な内容を取り上げました。Scrapyは、非常に機能が豊富で、かつ、拡張性が高いので、これをベースにカスタマイズしていけばWeb上から有用な情報を手軽に収集することができるようになります。

これからWebクローリングを始めようとしている人の手助けになれば幸いです。

*1:*.pycは省略

*2:scrapyはデフォルトで、間隔をランダムにずらす機能が有効になっているため、実際には、ここで設定した数値×0.5〜1.5秒間となります

*3:Ruleの引数の中に「callback='parse_item'」と指定されている

1年寝かせたEdisonのWi-Fi接続とFirmware(Yocto Linux)のアップデートにハマったのでメモ

ちょうど1年ぐらい前にIntel Edisonを買ったのですが、使わないまましまいこんだままになっていたので、掘り起こして動かして見ると、Wi-Fiつながらず、解決のために公式サイトの手順でFirmware(Yocto Linux)をアップデートしようとしたところ、素直に落としたYocto Linuxの最新イメージは、2.1、3.0と容量不足で入れられず。。。

ググったところ、2chのEdisonスレに同じような人がいて、そこに書いてある方法でアップデートできて、Wi-Fiまでつながったのでメモ。

参照した情報は以下。

383 :774ワット発電中さん:2015/10/31(土) 14:10:30.62 ID:gzX/MCJu
breakoutボードキットを試してるがWIFIがダメだ 
パスワード認識しIPアドレス取得まではうまくいくがpingが通らない 
edison側からも外からも 
ホストがない場合のunreachableはでずに永遠と沈黙 
WEBも反応しない 
5Gでも2Gでも症状同じ 
iwconfigやwpa_cli statusのメッセージも正常に見える 
無線LAN親機との相性ってあるんだろうか? 

ついでにいうとファームはRelease 2.0 Yocto* complete imageを使用 
2.1だと容量不足になる、フラッシュメモリ1GB搭載バージョンあるんか? 

自作はトラブルを楽しむためにやるもの、と考えれば 
楽しめているとも言える 

393 :774ワット発電中さん:2015/11/27(金) 22:22:52.47 ID:ddDflIs3
>>383 
同じとこでは待ってる奴発見w 
wifiできたぞ!w 
Edisonをまず最新の環境にアップデートするとこではまるよなw 
2.1は単純に容量不足になるw 
でも 
http://downloadcenter.intel.com/download/24910/Intel-Edison-Software-Release-2-1 
ここのFile name: edison-image-ww18-15.zipVersion: 2.1 (Latest) 
ならedisonのRAMでも容量が足りる! 

edisonのRAMを初期化フォーマットしてからにこのファイルを展開してedisonのRAM800Mくらいにコピー 

でedisonnにログインしてreboot ota やればOK 

configure_edison --setup で順に設定していってwifi設定すれば 

edisonのローカルサーバーアドレスが表示されるからブラウザからアクセスでけるようになってる! 

先人の知恵はありがたいです。

スレッドが落ちて、見られなくと困りそうなので、メモ


ここまでできたあとは、以下の手順にしたがって、AWS CLIのインストールまでできました。ここまでできれば、AWSが自由に使えるので、何でもできそうです。

github.com


紹介したスレには、2.1に上げる場合のコメントもあります。以下のサイトを参考にFlash Tool Liteを使えば、2.1にもできるようなので、それはまた今度試してみます。

IoT - The Intel® Edison Board Software Release 2.1 | Intel® Developer Zone