Scrapyを使用して企業名录データをスクレイピングしMySQLに保存する方法

Scrapyフレームワークを使用して企業名录 웹사이트から企業情報を取得し、MySQLデータベースに保存する方法を説明します。 примерно 22万件のデータを処理する必要があります。

第一步:Itemクラス定義

まず、スクレイピング対象のフィールドをItemクラスで定義します。
import scrapy


class CompanyItem(scrapy.Item):
    prefecture_name = scrapy.Field()
    district_name = scrapy.Field()
    company_name = scrapy.Field()
    company_address = scrapy.Field()
    telephone = scrapy.Field()
    mobile = scrapy.Field()

第二步:Spiderロジック実装

Spiderクラスを定義し、ウェブページの解析処理を実装します。
import scrapy
from scrapy.http import Request
from lxml import etree


class CompanySpider(scrapy.Spider):
    name = 'company_spider'
    
    def start_requests(self):
        base_url = 'http://example.business.jp/'
        yield Request(url=base_url, callback=self.parse_main)
    
    def parse_main(self, response):
        html_tree = etree.HTML(response.text)
        rows = html_tree.xpath('//table/tbody/tr')
        
        for row in rows:
            cells = row.xpath('./td[2]//a')
            for cell in cells:
                link = cell.get('href')
                if link:
                    full_url = 'http://example.business.jp/' + str(link)
                    yield Request(url=full_url, callback=self.parse_detail)
    
    def parse_detail(self, response):
        html_tree = etree.HTML(response.text)
        data_rows = html_tree.xpath('//table/tbody/tr')
        
        for record in data_rows[2:]:
            text_content = record.xpath('string()')
            field_list = text_content.replace(' ', '').replace('\r', '').split('\n')
            field_list = [f.strip() for f in field_list if f.strip()]
            
            attributes = record.xpath('./td[4]/@*')
            attr_value = attributes[-1].replace("'", '') if attributes else ''
            
            if '名称' in data_rows[1].xpath('string()').replace(' ', '').replace('\r', '').split('\n')[3]:
                prefecture = field_list[0] if len(field_list) > 0 else ''
                district = field_list[2] if len(field_list) > 2 else ''
                
                if record.xpath('./td[3]/@*')[-1].replace("'", '') == 'nowrap':
                    company = field_list[3] if len(field_list) > 3 else ''
                else:
                    company = attr_value
                    
                address = field_list[4] if len(field_list) > 4 else ''
                phone = field_list[5] if len(field_list) > 5 else ''
                mobile_phone = field_list[6] if len(field_list) > 6 else ''
            else:
                prefecture = field_list[2] if len(field_list) > 2 else ''
                district = field_list[3] if len(field_list) > 3 else ''
                company = attr_value
                address = field_list[5] if len(field_list) > 5 else ''
                phone = field_list[6] if len(field_list) > 6 else ''
                mobile_phone = field_list[7] if len(field_list) > 7 else ''
            
            item = CompanyItem()
            item['prefecture_name'] = prefecture
            item['district_name'] = district
            item['company_name'] = company
            item['company_address'] = address
            item['telephone'] = phone
            item['mobile'] = mobile_phone
            yield item

第三步:Pipeline設定

settings.pyでPipelineを有効化します。
ITEM_PIPELINES = {
   'company_spider.pipelines.CompanySpiderPipeline': 300,
}

第四步:データベース保存処理

PipelineクラスでMySQLへの保存処理を実装します。
import pymysql


class CompanySpiderPipeline:
    def __init__(self):
        self.connection = pymysql.connect(
            host='localhost',
            user='root',
            password='your_password',
            port=3306,
            database='company_db',
            charset='utf8mb4'
        )
        self.cursor = self.connection.cursor()
        self.cursor.execute("""
            CREATE TABLE IF NOT EXISTS company_directory (
                prefecture_name VARCHAR(100),
                district_name VARCHAR(100),
                company_name VARCHAR(200),
                company_address VARCHAR(200),
                telephone VARCHAR(50),
                mobile VARCHAR(50)
            )
        """)
        self.connection.commit()
    
    def process_item(self, item, spider):
        sql = '''INSERT INTO company_directory 
                 (prefecture_name, district_name, company_name, 
                  company_address, telephone, mobile) 
                 VALUES (%s, %s, %s, %s, %s, %s)'''
        
        try:
            self.connection.ping(reconnect=True)
            self.cursor.execute(sql, (
                item['prefecture_name'],
                item['district_name'],
                item['company_name'],
                item['company_address'],
                item['telephone'],
                item['mobile']
            ))
            self.connection.commit()
        except Exception as e:
            self.connection.rollback()
            spider.logger.error(f'Database error: {e}')
        
        return item
    
    def close_spider(self, spider):
        self.cursor.close()
        self.connection.close()
以上の実装により、大量の企業データを効率的にスクレイピングし、MySQLデータベースに保存することが可能になります。実行際は設定ファイルを適切に調整し、robots.txtの遵守やリクエスト間隔の調整など、マナー的なスクレイピングをお願いします。

タグ: Scrapy Python web-scraping MySQL データ抽出

8月13日 05:59 投稿