環境構築
Scrapyを使用するには、まず以下のコマンドでインストールを行います。
pip3 install scrapy
詳細なインストール手順については、公式の日本語ドキュメントを参照してください:Scrapyインストールガイド
プロジェクト作成とデータモデル定義
以下のコマンドで新しいScrapyプロジェクトを作成します。
scrapy startproject boss_job_scraper
items.pyファイルに、取得したいデータ項目を定義します。
import scrapy
class JobPosting(scrapy.Item):
job_id = scrapy.Field()
title = scrapy.Field()
labels = scrapy.Field()
experience = scrapy.Field()
compensation = scrapy.Field()
location = scrapy.Field()
qualification = scrapy.Field()
company_name = scrapy.Field()
industry = scrapy.Field()
funding_status = scrapy.Field()
company_scale = scrapy.Field()
posted_time = scrapy.Field()
scraped_at = scrapy.Field()
クローラー実装
spidersディレクトリ内にjob_spider.pyファイルを作成し、以下のように実装します。
import scrapy
import time
from boss_job_scraper.items import JobPosting
class BossJobSpider(scrapy.Spider):
name = 'boss_jobs'
allowed_domains = ['www.zhipin.com']
base_url = 'https://www.zhipin.com/c101020100/h_101020100/?query=python'
current_page = 1
custom_headers = {
'user-agent': "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
'accept': "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
'accept-language': "ja-JP,ja;q=0.9,en-US;q=0.8,en;q=0.7",
'cache-control': "no-cache"
}
def start_requests(self):
yield self.create_request()
def parse(self, response):
print(f"アクセス中: {response.url}")
jobs = response.css('div.job-list > ul > li')
for job_element in jobs:
posting = JobPosting()
primary_info = job_element.css('div.job-primary')
posting['job_id'] = job_element.css(
'div.info-primary > h3 > a::attr(data-jobid)'
).get().strip()
posting['title'] = primary_info.css(
'div.info-primary > h3 > a > div::text'
).get().strip()
posting['compensation'] = primary_info.css(
'div.info-primary > h3 > a > span::text'
).get().strip()
details = primary_info.css('div.info-primary > p::text').getall()
posting['location'] = details[0].strip()
posting['experience'] = details[1].strip()
posting['qualification'] = details[2].strip()
posting['company_name'] = primary_info.css(
'div.info-company > div.company-text > h3 > a::text'
).get().strip()
company_details = primary_info.css(
'div.info-company > div.company-text > p::text'
).getall()
if len(company_details) >= 3:
posting['industry'] = company_details[0].strip()
posting['funding_status'] = company_details[1].strip()
posting['company_scale'] = company_details[2].strip()
posting['labels'] = job_element.css(
'div.tags > span::text'
).getall()
posting['posted_time'] = job_element.css(
'span.time::text'
).get().strip()
posting['scraped_at'] = time.strftime(
"%Y-%m-%d %H:%M:%S", time.localtime()
)
yield posting
self.current_page += 1
time.sleep(3)
yield self.create_request()
def create_request(self):
url = f"{self.base_url}&page={self.current_page}"
return scrapy.http.Request(
url=url,
headers=self.custom_headers,
callback=self.parse
)
実行と出力
以下のコマンドでクローラーを実行し、結果をJSONファイルに出力します。
scrapy crawl boss_jobs -o jobs.json
日本語文字化けを防ぐため、settings.pyに以下の設定を追加します。
FEED_EXPORT_ENCODING = 'utf-8'
検索条件のカスタマイズ
検索条件を変更するには、job_spider.py内のbase_urlを修正します。例えば、職種を「Java」に、勤務地を「東京」に変更する場合、URLを適切に書き換えます。
改善点
- 各求人の詳細ページからさらに詳細な情報を抽出する機能が未実装
- 取得したデータに対する前処理ロジックが必要
- 重複データのフィルタリング機能の追加