無駄と文化

実用的ブログ

Scrapy のクローリング中に win32api が無くてコケる問題に対処(Windows10, 64bit, Python2.7)

f:id:todays_mitsui:20160827190511p:plain


昨日は Windows で Scrapy 1.1.2 をインストールするために必要な libxml2 のインストールについて解説しました。

blog.mudatobunka.org

が、どうやら Windows ではクローリングを実行するときにもう一つ win32api というライブラリが必要になるようです。
win32api が無いと、クローリングの実行中にコケます...。


状況再現

ひとまず適当な Spider を書いて走らせてみましょう。
月並みですが CNN.co.jp の記事一覧ページ から記事タイトルと URL を抜き出す Spider を書きます。

example/spiders/test.py

# -*- coding: utf-8 -*-

import scrapy


class TestSpider(scrapy.Spider):
    name = "test"
    allowed_domains = ["cnn.co.jp"]
    start_urls = (
        "http://www.cnn.co.jp/archives/",
    )

    def parse(self, response):
        articles = response.xpath("//ul[contains(@class,'story-list')]//a")

        for article in articles:
            title = article.xpath("./text()").extract_first()
            title = title and title.strip()

            url = article.xpath("./@href").extract_first()
            url = response.urljoin(url)

            yield {
                "title": title,
                "url": url,
            }

このように。


で、これを scrapy crawl test で走らせると、

f:id:todays_mitsui:20160828140247p:plain

f:id:todays_mitsui:20160828140254p:plain

コケます。


ImportError: No module named win32api」 というエラーが出ているので、まぁ、win32api が無いんでしょう。


この件については Scrapy の公式ドキュメントの FAQ に情報がありました。

Scrapy crashes with: ImportError: No module named win32api
You need to install pywin32 because of this Twisted bug.

はい、と言うわけで Twisted のバグに対処するために win32api が必要になってるみたいですね。
確かに以前のバージョンではこんなエラー出てなかったもんなぁ!

pywin32 をインストールしてくれと書かれているので、しましょう。


pywin32 をダウンロード

pip で簡単にインストールできないかとやってみたのですが、出来ず。
どうやら Windows 用に exe ファイルが配布されているようです。

こちらで配布されています。

なんかいきなり SourceForge が出てくると不安になるんですけど、どうやら公式の配布元みたいです。


README にも書かれているとおり最新のビルド(Build 220)のディレクトリの中からマシンやPythonのバージョンに合った exe ファイルをダウンロードします。
私は「pywin32-220.win32-py2.7.exe」を使いました。


pywin32 をインストール

exe ファイルなので普通にダブルクリックするだけでインストーラーが立ち上がるんですが、その方法だと virtualenv 環境から参照できません。
virtualenv 環境下にインストールするには、virtualenv 環境に入った状態で easy_install を使います。

env\Scripts\activate
easy_install pywin32-220.win32-py2.7.exe

すると、

f:id:todays_mitsui:20160828143045p:plain

f:id:todays_mitsui:20160828143052p:plain

上手く行ってそうですね。


再びクローリングを実行

気を取り直して scrapy crawl します。

scrapy crawl -o result.json test

今度は無事にクローリングが進んで結果が result.json という名前で保存されます。

result.json

[
  {
    "url": "http://www.cnn.co.jp/world/35088116.html",
    "title": "ボリビアの鉱山スト 交渉役の次官が撲殺、5人を逮捕"
  },
  {
    "url": "http://www.cnn.co.jp/usa/35088113.html",
    "title": "車のトランクから現金300万ドル押収 米・メキシコ国境"
  },

  /* ... 中略 ... */

  {
    "url": "http://www.cnn.co.jp/usa/35088101.html",
    "title": "ネオコン代表格、クリントン氏に投票を検討 「トランプ氏は危険」"
  }
]

データ、取れてます。

もう安心、あなたの顔が見えたから(2回目)


私からは以上です。

Scrapy インストール中に libxml2 が無くてコケる問題に対処(Windows10, 64bit, Python2.7)

f:id:todays_mitsui:20160827190511p:plain


Scrapy を最新版の v1.1.2 にしたくて pip install scrapy したらインストール中にコケました。

python -m virtualenv env
env\Scripts\activate
pip install scrapy

とやっても...

f:id:todays_mitsui:20160827175447p:plain

f:id:todays_mitsui:20160827175453p:plain

コケる。


なにやら libxml2 というライブラリが見つからないと言われています。

c:\windows\temp\xmlXPathInitu5z5db.c(1) : fatal error C1083: Cannot open include
file: 'libxml/xpath.h': No such file or directory

*********************************************************************************
Could not find function xmlCheckVersion in library libxml2. Is libxml2 installed?
*********************************************************************************

対処しましょう。


lxml をインストール

こちらのサイトを見ますと...

「pip での lxml のインストールが失敗した時は Windows 用のビルド済みバイナリを使ってくれ。非公式だけどね」と書いてあります。
なのでリンク先に飛んで Wheel ファイルをダウンロードします。

今回は「lxml-3.6.4-cp27-cp27m-win32.whl」を落としてきました。


では、コマンドプロンプトに戻りまして。

pip install lxml-3.6.4-cp27-cp27m-win32.whl

インストール実行!

f:id:todays_mitsui:20160827182446p:plain

はい、上手くいきました。

ここでもインストールに失敗する場合は別の Wheel ファイルを試してみてください。
Windows の 32bit/64bit の違い、Python のバージョンの違いによっても落としてくるべきファイルが違います。


再び Scrapy をインストール

lxml が無事インストールできたら、先ほどコケた Scrapy のインストールを再び行います。

pip install scrapy

今度は滞りなくうまくインストール完了しました。
バージョンは最新の v1.1.2 (2016年8月時点)。

f:id:todays_mitsui:20160827183739p:plain

もう安心、あなたの顔が見えたから


私からは以上です。


20160828 追記

Windows で Scrapy を利用するときにはもう一つ win32api というライブラリが必要になるようです。
こちらは pip install scrapy するだけでは入らないので別途インストール作業が必要です。

別記事を書きました。こちらも参照してください。

blog.mudatobunka.org

【jQueryの基本の"き"】パート2 - 起動スクリプトを詳しく解説

前回はjQueryプラグインを設置するための基本的な流れを解説しました。
今回はプラグインを使いこなすための要(かなめ)になる 起動スクリプト についてイメージしやすい例で解説していきます。


起動スクリプトとは

前回解説しましたが、jQuery本体やプラグインのJSファイルは通常、ページに読み込んだだけでは何も動作しません。
window にロードされて使える状態になってはいるものの、ページには何も影響を与えないわけです。

そこで、実際にjQueryプラグインを有意義に使うために 起動スクリプト を書く必要があります。


Slick というjQueryプラグインでは、こんな感じの起動スクリプトを書くだけでただの <ul> が写真めくりボタン付きのカルーセルに変身します。

<script>
jQuery(function($) {

  // ↓これが 起動スクリプト だ!
  $('.slides').slick({
    autoplay: true,
    prevArrow: '<button type="button" class="slick-prev">前へ</button>',
    nextArrow: '<button type="button" class="slick-next">次へ</button>',
  });

});
</script>

JavaScript を書き慣れない人にとっては、ただの記号の並びに見えてしまうかもしれません。
大丈夫、jQueryプラグインの起動スクリプトにはよく見かける鉄板のパターンがあります。鉄板パターンさえ押さえればいいんですよ。


起動スクリプトはどんな形をしているか

よく見かける鉄板パターンとは、前回も使ったこの画像に書かれているパターンです。

f:id:todays_mitsui:20160826230324p:plain

いかがです?
ポイントは起動スクリプトを3つのステップに分解して見てみることです。


ステップ1. 対象の要素を選択する

ステップ1はプラグインの対象を選んであげることです。
対象を指定する方法は簡単、Web畑の人間であれば慣れ親しんでいる CSSセレクター を使うことができます。

例えば、こんな感じの HTML があったとして、

<div class="container">
  <header>
    <h1 class="main-title">タイトルテキスト</h1>
    <p class="sub-title">Yet another タイトルテキスト</p>
  </header>

  <main>
    <section class="entry">
      <h2>記事のタイトル</h2>
      <article>
        <p>ここにテキストが入ります</p>
      </article>
    </section><!-- /.entry -->

    <section class="entry">
      <h2>二つめの記事タイトル</h2>
      <article>
        <p>ここにもテキストが入ります</p>
      </article>
    </section><!-- /.entry -->
  </main>
</div><!-- /.container -->

この中で、タイトルテキストのh1要素をjQueryで選択してみましょう。
なぁに、むつかしく考える必要はありません。jQueryのことはいったん忘れて、「このタイトルテキストの色を赤に変えて」と言われていつもの CSS を書く時のことを思い浮かべればいいんです。


きっとこんな感じになりますよね。

<script>
$('.main-title')
// => タイトルテキストのh1要素が選択されている
</script>

h1要素には偶然にも “main-title” というclass名がついていたのでそれを利用しました。
$() というのが対象を選択してくれる便利なやつです。
$ って何でしたっけ? そう、jQuery の別名ですね。jQueryにCSSセレクターを渡すとその要素を選択してくれます

セレクターの書き方ですが、もちろんタグ名を使って、

<script>
$('h1')
// => タイトルテキストのh1要素が選択されている
</script>

と書いたり。

合わせ技で、

<script>
$('h1.main-title')
// => タイトルテキストのh1要素が選択されている
</script>

と書いてもオッケィです。


さらに、CSS で複数の要素にスタイルを適用するときのように、1つのCSSセレクターで複数の要素を選択することもできます。

先ほどの HTML には記事の本文らしきp要素がふたつありましたね。
捕まえてみましょう。

<script>
$('.entry p')
// => 記事の本文(2つある!)の全てが選択されている
</script>

今回は「class=“entry” の内側にあるp要素」といった指定の仕方をしました。
その他、CSS3を含めたあらゆるセレクター :nth-child(odd)div > p やそれらの組み合わせも問題なく認識してくれます。

CSSセレクターさえ知っていれば、要素の選択は恐るるに足らずですね。


ステップ2. 適用するプラグイン名を選ぶ

要素を選択したら、その後に ドット. を繋いでプラグイン名を続けます。
前回使った Slick であれば .slick を続けて書きます。

<script>
$('.entry p').slick
// => 選択した要素に対して "Slick" を使うぞ!という意思表示
</script>

プラグイン名は大体公式サイトの目につくところに書いてあるはずなので、それをコピペなりしてください。

その他に、jQuery標準の機能も同様に書くことができます。
例えば対象要素の CSS を書き替える機能はズバリ .cssです。そのままですね。

<script>
$('.entry p').css
// => 選択した要素の CSS を書き替えてやるぞ!という意思表示
</script>

簡単ですね。これでもう8割がた終わってます。


ステップ3. プラグインにオプションを指定する

先ほど、ドット. に続けてプラグイン名を書きましたが、これだけではまだプラグインは発動しません。
あくまでも意思表示して構えただけです。引き金を引くのはこれから。

最後の仕上げでプラグイン名の後ろに 丸カッコ() を付けましょう。

<script>
$('.entry p').slick()
// => 丸カッコ() を付けた瞬間プラグインが発動します。引き金を引くような感覚ですね
</script>

ご存知のとおり丸カッコの中にはオプションを書き込むことも出来ます。
出来ますが、仮にオプションを書かない場合でも丸カッコだけは書かなければいけません。
丸カッコを省略してしまうと 何も起こりません

オプションを渡してみましょう。前回も書いた {autoplay: true} というオプションを書き込みます。

<script>
$('.entry p').slick({autoplay: true})
// => オプションを渡した書き方
//    コロン: で区切って左側がオプション名、右側がオプションの値
</script>

これにて Slick は私たちの意志を察して オートプレイ(ボタンを押さなくても一定時間で写真をめくる動作) をしてくれるようになります。



さて、ここまででjQueryの起動スクリプトを3ステップに分けて解説してきました。

  1. $() で対象の要素を選択して
  2. 適用するプラグイン名を ドット. で繋いで
  3. オプションを渡しつつ 丸カッコ() を付ける
    (オプションが無くても () は絶対に付ける!)

たったの3ステップ。簡単ですね。


ところでWeb畑にお住まいのみなさん、この3ステップ、何かに似ていませんか?

そう、イラレこと Adobe Illustorator の使い方にそっくり ですよね。


「jQuery = イラレ」仮説

と言うわけで、jQuery と イラレ がどんだけ似ているか証拠VTRをお見せしましょう。

私、先ほど「jQuery標準機能で要素のCSSを書き替えられる」って言いませんでした?言いましたよね。
ご覧下さい。

1. 対象の要素を選択して

f:id:todays_mitsui:20160827011510p:plain

2. 適用する機能を選んで

f:id:todays_mitsui:20160827011515p:plain

3. オプション(背景色)を指定しつつ実行

f:id:todays_mitsui:20160827011521p:plain


これをjQueryでやると…

<script>
// ↓1. 対象の要素を選択して
                //↓2. 適用する機能を選んで
$('div.square01').css({
  backgroundColor: 'rgb(100,220,150)'
});
// ↑3. オプション(背景色)を指定しつつ実行
</script>

完全に似てる。


ついでに先ほど「複数の要素を選択できる」とも言いませんでした?言いましたね。
はい、どうぞ。

1. 複数の対象の要素を選択して

f:id:todays_mitsui:20160827011529p:plain

2. 適用する機能を選んで

f:id:todays_mitsui:20160827011536p:plain

3. オプション(今度はボーダー色)を指定しつつ実行

f:id:todays_mitsui:20160827011545p:plain


jQueryだと…

<script>
// ↓1. 複数の対象の要素を選択して
                            //↓2. 適用する機能を選んで
$('div.square02, div.circle').css({
  borderColor: 'red'
});
// ↑3. オプション(ボーダー色)を指定しつつ実行
</script>

完 全 に 一 致 。


そんなわけで、イラレを使いこなしているWeb畑の人たちは無意識のうちにjQueryをマスターしていると言っても過言ではない(過言ではある)んです。

記号の並びにしか見えなかった起動スクリプトに親しみが湧いてきましたよね?


起動スクリプトを囲っている アレ をひもとく

ところで、いちばん最初に登場したきり軽やかにスルーされている、こちらのよく見る記述も気になりますよね?

<script>
// ↓よく見る・気になるこの記述
jQuery(function($) {

  /* ここに起動スクリプトが書かれていた */

});
</script>

コレについても全力で解説したい気持ちはやまやまですが、コレについては次回(パート3)に続けさせてください。


まとめ

今回は記号の並びにしか見えなかった起動スクリプトに親しみを持ってもらうために、イメージをかき立てる解説をしてきました。
簡単にまとめると、

  • 起動スクリプトは「1.対象選択」「2.プラグインを選ぶ」「3.オプションを渡しつつ実行」の3ステップ
  • jQuery と イラレ はめっちゃ似ている

というお話でした。


私からは以上です(続く)


【jQueryの基本の"き"】シリーズ

blog.mudatobunka.org

blog.mudatobunka.org

blog.mudatobunka.org