Published Date : 2020年9月25日7:49

【python】住所を使ったデータ処理:spider
【python】Data processing using address: spider


This blog has an English translation


YouTubeにアップした動画、「【python】住所を使ったデータ処理:spider」の補足説明の記事です。

Here's a little more about the 「【python】Data processing using address: spider」 video I uploaded to YouTube.


目次

Table of Contents




① 動画の説明
① Video Description



前回同様にscrapyのコマンドを使って、プロジェクトを作成します。

Create the project using the scrapy command as before.

scrapy startproject scrapy_test

そしてプロジェクトのフォルダに移動して、スパイダーを作成します。

Then go to the project's folder and create a spider.

cd scrapy_test
scrapy genspider example "www.test.test"

スパイダーフォルダの中にあるPythonファイルを開き、

Open the Python file in the spider folder

そこに前回のShellで書いたスクリプトを書き写していきます。

and copy the script you wrote in the last Shell.

その前にスクレイピングして取得したデータを格納するItemクラスを作成しておきましょう。

Before that, let's create an Item class to store the scraped data.

# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html

import scrapy


class ScrapyTestItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    zip_code = scrapy.Field()
    address1 = scrapy.Field()
    address2 = scrapy.Field()

start_urlsに検索したい都道府県のURLを指定しておきます。

Set start_urls to the URL of the prefecture you want to search.

data_path = r"C:\Users\script\data"
prefecture_list = ["茨城", "栃木", "群馬", "埼玉", "千葉", "東京", "神奈川", "静岡"]

saitama_city_list = pd.read_csv(data_path + rf'\{prefecture_list[3]}city.csv')

start_urls = saitama_city_list['link'].apply(lambda x: 'http://www.test.test' + x).to_list()

最初の県の都市リストを格納して、都市ごとに再帰的に全ての番地を取得できるように、

It stores a list of cities in the first prefecture, and uses the pop method to search the elements

prefecture_linkに格納した要素をpopメソッドを用いて一件ずつ検索していきます。

stored in preference_link one by one so that all addresses can be retrieved recursively for each city.

scrapyのRequestメソッドをyieldではなく、returnで返すのがポイントです。

The point is to return the scrapy Request method with return instead of yield.

popメソッドを簡単にデモンストレーションします。

A brief demonstration of the pop method.

リストオブジェクトを作成して、このメソッドを使用すると、

Create a list object and use this method to retrieve

リストの一番後ろの要素が取り出せれ、それは変数に収めることもできます。

the last element of the list, which can also be stored in a variable.

In : l = list(range(10))

In : l
Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In : while l:
...:     popd_l = l.pop()
...:     print(l)
...:     print(popd_l)
...:
[0, 1, 2, 3, 4, 5, 6, 7, 8]
9
[0, 1, 2, 3, 4, 5, 6, 7]
8
[0, 1, 2, 3, 4, 5, 6]
7
[0, 1, 2, 3, 4, 5]
6
[0, 1, 2, 3, 4]
5
[0, 1, 2, 3]
4
[0, 1, 2]
3
[0, 1]
2
[0]
1
[]
0

parseメソッドはスパイダーが起動し、先ほどのstart_urlsにアクセスした時に、

The parse method is a function that runs automatically

自動で最初に一度だけ実行される関数です。

the first time the spider starts and accesses start_urls.

ここで市区町村のリストを取得してyieldを使ってyield_linkを呼び出せば、

Now you can get a list of cities and use yield to call yield_link.

prefecture_linkが空になるまで次のparse_itemメソッドをyield_linkが呼び出してくれます。

yield_link will call the next parse _ item method until the preference_link is empty.

self.all_link = list(set([next_page.get() for next_page in next_page_link]))
yield self.yield_link()

parse_itemメソッドで市区町村毎にある全ての住所リンクを取得して、

The parse_item method retrieves all address links for each city, uses the for statement,

for文を使い、その中でyieldを使用してリストが空になるまで再帰的に住所を取得してきます。

and then recursively retrieves addresses using yield until the list is empty.

ここで簡単にyieldとreturnの違いをデモンストレーションします。

Here is a simple demonstration of the difference between yield and return.

returnを使用すると、関数はreturnで結果を返して処理を終了する。

If you use return, the function returns the result and terminates.

yieldを使用すると、yieldの直前までの処理が一旦中断し、そこまでの結果を返します。

If you use yield, the process up to and including yield is suspended and the result is returned.

この関数をループ処理すると、yieldの次処理から再開します。

When this function is looped, it resumes with the next step in yield.

引数にレスポンスがくるまで処理を待機するので、

The callback function is used for asynchronous processing,

コールバック関数は非同期処理等に使用されます。

for example, because it waits for a response to the argument.

このコールバック関数にyieldを持つ自身の関数を使用することによって、

By using its own function with yield in this callback function,

住所リンクの一番深い階層までURLを辿っていき、

you can follow the URL to the deepest level

次のリンクが存在しないページなら表示されている住所を取得して、

of the address link, get the displayed address if the next link doesn't exist,

最終的には一番最初のFor文に戻り、一番深い階層から順次住所を取得できます。

and finally return to the first For statement to get the addresses from the deepest level down.

if self.nested_link != []:
    for link in self.nested_link.pop():
        next_url = 'http://www.test.test' + link
        yield scrapy.Request(next_url, callback=self.parse_item_list, dont_filter=True)

後はいつもの様にsettingspyに以下の四つを設定して、

Then, as usual, set settingspy to the following four,

ROBOTSTXT_OBEY = True

DOWNLOAD_DELAY = 3

HTTPCACHE_ENABLED = True

FEED_EXPORT_ENCODING = 'utf-8'

scrapyのcrawlコマンドを使用して、クロールを開始します。

and use the scrapy crawl command to start crawling.

scrapy list
example

scrapy crawl example -o example.json

リンク一つに対してリクエストするため、ダウンロードディレイが3秒に設定されていると、

Since the request is made for one link,

結構な時間がかかります。辛抱強く待ちましょう。

it takes a long time if the download delay is set to 3 seconds. Let's wait patiently.



以上です。お疲れ様です。

That's all. Thank you for your hard work.