こんにちわ、タカです。今日も寒いですね。さて、今回は前回に引き続きPythonの『Scrapy』ネタになります。今回はクローリングするurlを動的に設定する方法を紹介します。
Scrapyとは、Pythonのクローリング・スクレイピングのフルスタックフレームワークになります。とても強力で便利なフレームワークになり、冗長的な処理をフレームワーク側がやってくれるので、クローリング・スクレイピング処理に集中することができます。
なお、今回のコードはScrapyのバージョン1.4.0をベースにしたものです。
さて、前回と同様、まずはScrapyのSpiderクラスのサンプルコードをみていきましょう。
import scrapy
class MySpider(scrapy.Spider):
name = 'example'
allowed_domains = ['example.com']
start_urls = [
'http://www.example.com/1.html',
'http://www.example.com/2.html',
'http://www.example.com/3.html',
]
def parse(self, response):
for h3 in response.xpath('//h3').extract():
yield {"title": h3}
上のコードは、Spiderクラスの基本となるようなコードで、これが実際に何をしているのかを簡単に言うと、「example」という名前のSpiderが、「start_urls」に記載されてあるurlをクローリングして、それぞれのページにある「h3」タグのタイトルを取得しています。
ここまでは前回の記事と同じになりますが、今回はクローリングするURLを動的に設定してみたいと思います。上のコードで言えば 「start_urls」で設定しているurlを動的に設定するということになります。なお、今回はMySQLからurlを取得するケースを想定してコーディングしたいと思います。
クローリングするurlを動的に設定するには、「start_requests」メソッドを使います。ちなみに、上のコードでは「start_requests」メソッドは省略されている形になります。
では、実際にコードを作成していきましょう。
まず、上のコードを少しカスタマイズして「start_requests」メソッドを追加します。
import scrapy
import MySQLdb
from scrapy.utils.project import get_project_settings
class MySpider(scrapy.Spider):
name = 'example'
def start_requests(self):
def parse(self, response):
for h3 in response.xpath('//h3').extract():
yield {"title": h3}
上のコードでは、まずmysqlを使用するために「MySQLdb」ライブラリと、settings.pyを参照するために「get_project_settings」ライブラリをimportしています。
また、urlは動的で設定するため、「allowed_domains」と「start_urls」は削除しています。
つづいて、「start_requests」メソッドにMySqlからデータを取得するコードを追加していきます。
import scrapy
import MySQLdb
from scrapy.utils.project import get_project_settings
class MySpider(scrapy.Spider):
name = 'example'
def start_requests(self):
settings = get_project_settings()
params = {
'host': settings.get('MYSQL_HOST', 'localhost'),
'db': settings.get('MYSQL_DATABASE', ''),
'user': settings.get('MYSQL_USER',''),
'passwd': settings.get('MYSQL_PASSWORD',''),
'charset': settings.get('MYSQL_CHARSET', 'utf8mb4'),
}
self.conn = MySQLdb.connect(**params)
self.c = self.conn.cursor()
sql = 'select url from urls'
self.c.execute(sql)
urls = self.c.fetchall()
self.conn.commit()
self.conn.close()
def parse(self, response):
for h3 in response.xpath('//h3').extract():
yield {"title": h3}
上のコードは、「start_requests」メソッドでDBに接続してデータを取得しているのですが、一つずつ見ていきましょう。
まず「get_project_settings」を使って、settings.pyのデータを取得しています。そして、「params」ディクショナリにてDB接続に必要な情報を設定しています。ここでは、settings.pyで設定したデータを参照しています。例えば、下のコードはsettings.pyの「MYSQL_HOST」を参照しており、もしsettings.pyに「MYSQL_HOST」データがない場合は、「localhost」を設定するということになります。
settings.get('MYSQL_HOST', 'localhost')
DB接続に必要な情報を設定したら、下記コードで実際にDBに接続しています。
self.conn = MySQLdb.connect(**params)
self.c = self.conn.cursor()
DBに接続したら、下記コードでsql文を設定して実行しています。ここでは「urls」というテーブルからurlフィールドを取得すると仮定しています。
sql = 'select url from urls'
self.c.execute(sql)
urls = self.c.fetchall()
self.conn.commit()
これで、DBからデータを取得することができました。
そして最後に、取得したurlをクローリングするためのコードを追加します。
import scrapy
import MySQLdb
from scrapy.utils.project import get_project_settings
class MySpider(scrapy.Spider):
name = 'example'
def start_requests(self):
settings = get_project_settings()
params = {
'host': settings.get('MYSQL_HOST', 'localhost'),
'db': settings.get('MYSQL_DATABASE', ''),
'user': settings.get('MYSQL_USER',''),
'passwd': settings.get('MYSQL_PASSWORD',''),
'charset': settings.get('MYSQL_CHARSET', 'utf8mb4'),
}
self.conn = MySQLdb.connect(**params)
self.c = self.conn.cursor()
sql = 'select url from urls'
self.c.execute(sql)
urls = self.c.fetchall()
self.conn.commit()
for url in urls:
yield scrapy.Request(
url[0],
callback=self.parse
)
self.conn.close()
def parse(self, response):
for h3 in response.xpath('//h3').extract():
yield {"title": h3}
DBから取得したurlデータをfor文でループしてクローリングリクエストをしています。これでダウンロードされたページは「parse」メソッドでパースされるという形になります。
なお、補足として「start_requests」メソッドではなく、「__init__」メソッドでも同様のことはできます。
以上、PythonのScrapyでクローリングするurlを動的に設定する方法でした。ご参考になれば幸いです。
それでは、今回はここまで。また!
この記事のまとめ
- PythonのScrapyでクローリングするurlを動的に設定する