Scrapy將數據保存到Excel和MySQL中的方法實現

Scrapy是一個用Python實現的為瞭爬取網站數據、提取數據的應用框架。我們對於爬取到的數據存儲到本地或數據庫是經常要用到的操作。主要講解兩種保存方式:

  • Excel
  • MySQL

說明一下爬取到的數據:

爬取豆瓣讀書top250網頁的相關信息:

書名title、鏈接link、國傢country、作者author、翻譯者translator、出版社publisher、出版時間time、價格price、星級star、評分score、評分人數people、簡介comment

請添加圖片描述

1. Excel

主要講解兩種方式:openpyxlpandas

1.1 openpyxl

class ExcelPipeline:
    def __init__(self):
        # 創建Excel文件
        self.wb = Workbook()
        # 選取第一個工作表
        self.ws = self.wb.active
        # 寫入表頭
        self.ws.append(['title', 'link', 'country',
                        'author', 'translator', 'publisher',
                        'time', 'price', 'star', 'score',
                        'people', 'comment'
                        ])

    def process_item(self, item, spider):
        self.ws.append([
            item.get('title', ''),
            item.get('link', ''),
            item.get('country', ''),
            item.get('author', ''),
            item.get('translator', ''),
            item.get('publisher', ''),
            item.get('time', ''),
            item.get('price', ''),
            item.get('star', ''),
            item.get('score', ''),
            item.get('people', ''),
            item.get('comment', '')
        ])
        return item

    def close_spider(self, spider):
        self.wb.save('result.xlsx')

1.1.1 代碼說明

ExcelPipeline 繼承自 Scrapy 的 Pipeline 類,並重寫瞭三個方法:__init__()process_item()close_spider()

__init__() 方法中:

  • 創建瞭一個 Excel 文件,並選取瞭第一個工作表。然後,我們寫入瞭表頭。
  • 當然你也可以將這部分代碼寫在open_spider方法中

process_item() 方法中,我們將每一行的數據寫入到工作表中。

process_item 方法:

  • 不會覆蓋之前已經寫入的數據,它會在數據末尾追加新的行。
  • 你調用多次 process_item 方法,每次都會在表格的末尾追加一行新數據。

close_spider() 方法中,我們保存 Excel 文件。

1.1.2 註意

可以發現我在process_item()方法中使用瞭item.get(key, default)

考慮可能存在某些 item 中沒有某些鍵值的情況,這可能會導致程序出錯。

當然如果你已經進行過數據處理也可以直接用item[key]

使用瞭 item.get(key, default) 方法來獲取 item 中的鍵值,如果某個鍵不存在,則返回一個空字符串 ''

在 Scrapy 中,item 是一個字典類型,它由一系列鍵值對組成,每個鍵值對表示一個字段。在處理 item 時,我們通常需要從中獲取某個字段的值。使用字典的 get 方法可以方便地實現這個功能。

get 方法有兩個參數:key 表示要獲取的鍵,default 表示鍵不存在時的默認值。例如:

1.2 pandas

class ExcelPipeline:
    def __init__(self):
        # 創建一個空的數據框
        self.df = pd.DataFrame(columns=['title', 'link', 'country',
                                        'author', 'translator', 'publisher',
                                        'time', 'price', 'star', 'score',
                                        'people', 'comment'
                                        ])

    def process_item(self, item, spider):
        # 將數據添加到數據框中
        item['title'] = item.get('title', '')
        item['link'] = item.get('link', '')
        item['country'] = item.get('country', '')
        item['author'] = item.get('author', '')
        item['translator'] = item.get('translator', '')
        item['publisher'] = item.get('publisher', '')
        item['time'] = item.get('time', '')
        item['price'] = item.get('price', '')
        item['star'] = item.get('star', '')
        item['score'] = item.get('score', '')
        item['people'] = item.get('people', '')
        item['comment'] = item.get('comment', '')
        series = pd.Series(item)
        self.df = self.df.append(series, ignore_index=True)
        return item

    def close_spider(self, spider):
        # 將數據框保存到 Excel 文件中
        self.df.to_excel('result.xlsx', index=False)

1.2.1 代碼說明

定義瞭一個 ExcelPipeline 類,它包含瞭三個方法:__init__process_itemclose_spider

  • __init__ 方法用於初始化類實例
  • process_item 方法用於處理每個爬取到的 item,將其添加到 items 列表中
  • close_spider 方法用於在爬蟲關閉時將 items 列表中的數據保存到 Excel 文件中。

1.2.2 常見錯誤

在代碼中有大量的item['title'] = item.get('title', '')類似代碼

你可以選擇不寫,但如果item中有一些字段的值為None,而pandas不支持將None類型的值添加到DataFrame中,會導致程序錯誤。這一點比openpyxl要嚴格的多。

字典對象轉換為Series對象

self.df是一個DataFrame對象,而item是一個字典對象。因此,需要將字典對象轉換為Series對象,然後再將其添加到DataFrame中。

series = pd.Series(item)
self.df = self.df.append(series, ignore_index=True)

only Series and DataFrame objs are valid這個錯誤一般就是發生在使用Pandas將數據轉換成DataFrame時,傳入的參數不是Series或DataFrame類型。

上面的代碼就是用來避免這個問題的。

1.3 openpyxl和pandas對比

pandas和openpyxl都是非常強大的Python數據處理庫,兩者在不同的場景下可以發揮出各自的優勢。

  • 如果需要處理大量的Excel文件,需要對文件進行復雜的操作,比如格式化、圖表等,那麼openpyxl可能更適合,因為它專註於Excel文件的讀寫和操作,具有更高的靈活性和控制力。
  • 如果數據已經在Python中,且需要進行各種統計分析和處理,如數據聚合、數據透視表、數據分組、數據清洗、數據可視化等,那麼pandas可能更適合,因為它提供瞭豐富的數據處理工具和函數。

總的來說,兩者都是很好的工具,具體使用哪一個取決於具體需求和場景。

2. MYSQL

可以使用Python的MySQL驅動程序,例如 mysql-connector-pythonpymysql。主要將pymysql。

class MySQLPipeline:
    def __init__(self):
        # 連接 MySQL 數據庫
        self.conn = pymysql.connect(
            host='localhost',
            port=3306,
            user='root',
            password='your_password',
            database='your_database',
            charset='utf8mb4',
            cursorclass=pymysql.cursors.DictCursor
        )
        # 創建一個遊標對象
        self.cursor = self.conn.cursor()
        # 創建表
        self.create_table()

    def create_table(self):
        # SQL 語句:創建數據表
        sql = '''CREATE TABLE IF NOT EXISTS `book` (
            `id` int(11) NOT NULL AUTO_INCREMENT,
            `title` varchar(255) NOT NULL,
            `link` varchar(255) NOT NULL,
            `country` varchar(255) NOT NULL,
            `author` varchar(255) NOT NULL,
            `translator` varchar(255) NOT NULL,
            `publisher` varchar(255) NOT NULL,
            `time` varchar(255) NOT NULL,
            `price` varchar(255) NOT NULL,
            `star` varchar(255) NOT NULL,
            `score` varchar(255) NOT NULL,
            `people` varchar(255) NOT NULL,
            `comment` varchar(255) NOT NULL,
            PRIMARY KEY (`id`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci'''
        # 執行 SQL 語句
        self.cursor.execute(sql)
        # 提交事務
        self.conn.commit()

    def process_item(self, item, spider):
        # SQL 語句:插入數據
        sql = '''INSERT INTO `book` (
                `title`, `link`, `country`,
                `author`, `translator`, `publisher`,
                `time`, `price`, `star`, `score`,
                `people`, `comment`
            ) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'''
        # 執行 SQL 語句
        self.cursor.execute(sql, (
            item['title'], item['link'], item['country'],
            item['author'], item['translator'], item['publisher'],
            item['time'], item['price'], item['star'], item['score'],
            item['people'], item['comment']
        ))
        # 提交事務
        self.conn.commit()
        return item

    def close_spider(self, spider):
        # 關閉遊標對象
        self.cursor.close()
        # 關閉數據庫連接
        self.conn.close()

2.1 代碼說明

我們創建瞭一個名為MySQLPipeline的自定義ScrapyPipeline。

__init__方法中接收瞭MySQL數據庫的配置信息。

其中還調用瞭create_table,當然如果保證表已經存在,也沒有必要這麼寫

如果你嫌每次連接都要寫信息的話,可以在setting.py中定義MySQL相關變量:

image-20230207083635621

請添加圖片描述

create_table方法創建表book

process_item方法用於將抓取的數據插入到數據庫表中。

close_spider方法用於關閉遊標和連接。

2.2 pymysql介紹

2.2.1 遊標對象

在Python中,連接數據庫時需要創建一個數據庫連接對象,然後通過這個連接對象創建一個遊標對象

遊標對象是執行數據庫操作的主要對象,它負責向數據庫發送查詢和獲取結果。

在Python中,常用的遊標對象有CursorDictCursorSSCursor等。

  • Cursor:普通遊標(默認),返回結果為元組類型。
  • DictCursor:字典遊標,返回結果為字典類型。
  • SSCursor:嵌套遊標,可用於處理大數據集。

在獲取大量數據時效率比普通遊標更高,但是會占用更多的系統資源。

與普通遊標相比,嵌套遊標不會將整個查詢結果讀入內存,而是每次隻讀取部分數據。

根據需要,選擇不同類型的遊標對象可以方便我們對返回結果進行處理。

2.2.2 各種遊標說明

創建連接對象時有這麼一段代碼:

cursorclass=pymysql.cursors.DictCursor

用於設置遊標返回的數據類型,默認返回的是元組(tuple)類型,設置為DictCursor後可以返回字典(dict)類型,更方便處理數據。一般使用普通遊標就行瞭

三種遊標主要是在查詢時的方式存在區別:

cur = conn.cursor()
cur.execute('SELECT * FROM my_table')
result = cur.fetchone()  # 獲取一條記錄,返回的是元組類型
# 普通遊標
print(result[0])  # 訪問第一個字段的值
# 字典遊標
print(result['id'])  # 訪問數據庫中字段名為 id 的字段的值,{'id': 1, 'name': 'Alice'}

# 嵌套遊標
print(result[0])  # 訪問第一個字段的值

如果是查詢的多條數據,則返回的是元組或字典組成的列表:

# 普通遊標
[(1, 'John', 'Doe'), (2, 'Jane', 'Doe'), (3, 'Bob', 'Smith')]
# 字典遊標
[{'id': 1, 'first_name': 'John', 'last_name': 'Doe'}, {'id': 2, 'first_name': 'Jane', 'last_name': 'Doe'}, {'id': 3, 'first_name': 'Bob', 'last_name': 'Smith'}]

3. 特別說明

每個item在被提交給管道時都會調用一次管道類的process_item方法。

每個item都會經過process_item方法進行處理,而open_spiderclose_spider方法隻會在爬蟲啟動和結束時執行一次。

在Scrapy中,可以通過在管道類的open_spiderclose_spider方法中建立和關閉數據庫連接,以減少連接建立和關閉的次數。

__init__方法也是隻在Spider啟動時隻執行一次

具體做法是,在open_spider方法中建立數據庫連接,在process_item方法中使用連接對數據進行存儲操作,在close_spider方法中關閉連接。這樣做可以有效減少連接的建立和關閉次數,提高爬取效率。

如果你在open_spider方法中創建瞭數據庫連接,那麼這個連接將會被共享並被多個process_item方法使用。

同樣的,如果在close_spider方法中關閉瞭數據庫連接,那麼這個連接也會被所有的process_item方法共享並在爬蟲結束時關閉。

這種做法可以減少不必要的連接和關閉操作,從而提高性能。

到此這篇關於Scrapy將數據保存到Excel和MySQL中的方法實現的文章就介紹到這瞭,更多相關Scrapy數據保存到Excel和MySQL內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: