Scrapy 爬取不同網站及自動執行的經驗分享

MirrorTan發表於2020-11-16

距離上一篇部落格的分享已經過去…嗯,好久時間了,最近在玩爬蟲,分享一點個人的經驗。

1 問題

最近接到一個需求,要寫一個爬蟲程式:

  • 需要抓取不同網站的資料,舉例如同時抓取「淘寶」、「京東」商品詳情頁。
  • 需要將資料存入到資料庫中,抓取完成後對資料進行簡單分析處理。
  • 需要將爬蟲日誌、統計資訊及資料分析結果傳送到指定郵箱。
  • 需要定期自動執行。

2 分析整理

我計劃使用 Scrapy 框架來寫爬蟲程式實現:

  • Scrapy 中不同 Spider 解析不同的網頁,可實現不同網站的抓取;
  • Scrapy 中可通過 Pipeline 實現資料庫的寫入操作;
  • 可在 Scrapy 一級目錄下寫分析模組實現資料分析功能;
  • 可藉助於 CrawlerProcess 實現 multi spider 執行;
  • 將所有功能整合進 run.py 中,使用 Linux 中的 crontab 實現自動執行。

最終的程式目錄結構如下:

├── Pipfile
├── Pipfile.lock
├── README.md
├── run.py
├── scrapy.cfg
└── ScrapyTest
    ├── __init__.py
    ├── items.py
    ├── middlewares.py
    ├── pipelines.py
    ├── settings.py
    └── spiders
        └── __init__.py
        └── taobao.py
        └── jingdong.py
└── utils
    ├── __init__.py 
    ├── db.py 
    ├── email.py
    ├── preanalysis.py
    ├── settings.py

說明:這裡使用的的 Python 環境管理工具是 pipenv,最終部署環境是在一臺 CentOS 伺服器上。

3 具體實現

因為只是舉例說明下思路,所以並沒有給出完整的程式碼,主要分享的是執行的指令碼 run.py 以及在 CentOS 中自動執行的處理。

3.1 run.py

from scrapy import spider_loader
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings

from utils.email import send_email
from utils.preanalysis import analysis

def run_spider():
    '''
    執行爬蟲
    '''
    settings = get_project_settings()
    process  = CrawlerProcess(settings)
    spider_loader = spiderloader.SpiderLoader.from_settings(settings)

    # 將 spider 逐個新增到 CrawlerProcess 例項及 crawlers 列表中
    crawlers = []
    for spider in spider_loader.list():
        logger.info(f'Running spider {spider}')
        crawler = process.create_crawler(spider)
        crawlers.append(crawler)
        process.crawl(crawler)

    # 開始爬蟲
    process.start()

    # 獲取爬蟲的統計資訊
    stats_dict = {}
    for crawler in crawlers:
       stats_dict[crawler.spider.name] = crawler.stats.get_stats()

    return stats_dict

def main():
    # 執行爬蟲
    spider_stats = run_spider()

    # 對結果進行簡單分析處理
    analysis_stats = analysis()

    # 傳送結果到指定郵箱
    send_email(analysis_stats, spider_stats)

if __name__ == "__main__":
    main()

3.2 實現自動執行

由於是部署在 Linux 伺服器上,可藉助 cron 來實現自動執行的功能。

cron (crond) 是用於控制迴圈工程排程的系統服務,可通過 crontab 指令建立自己的例行工作排程:

# 新建排程
$ crontab -e
# 此時會進入 vi 的編輯畫面讓您編輯工作!注意到,每項工作都是一行。
5   5 *  *  1 bash /pathto/auto-spider.sh
#分 時 日 月 周 |<==============指令串========================>|
# 檢視排程
$ crontab -l
5   5 *  *  1 bash /pathto/auto-spider.sh

這裡的意思時每週一五點零五分執行 auto-spider.sh ~ 這裡不是直接執行 run.py 而是執行一個 auto-spider.sh 指令碼 ~ 是為了在 Python 虛擬環境中執行爬蟲程式。

auto-spider.sh 指令碼示例如下:

cd /pathto/ScrapyTest
PATH=/usr/local/bin:$PATH
pipenv run python run.py

4 參考資料

  1. CrawlerProcess 官方文件:docs.scrapy.org/en/latest/topics/p....

  2. 參考案例:stackoverflow.com/questions/393651....

  3. Crontab 教程:linux.vbird.org/linux_basic/centos....

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章