爬蟲微博 Django(3.0) Scrapy Celery Supervisor

  1. 搭建Django Server,用Django(Version 3.0)創建一個app,作爲爬蟲的入口;
  2. 用Django的Model創建數據庫模型,數據庫用的是Mysql;
  3. 跟Django 的app同目錄創建一個Scrapy項目,先單獨編寫爬蟲的代碼,讓爬蟲可以正常運行,爬蟲微博使用的是Cookie的方式,先從網頁瀏覽器中登錄微博,獲取Cookie,把Cookie放到Scrapy Settings.py 的DEFAULT_REQUEST_HEADERS裏
DEFAULT_REQUEST_HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0',
    'Cookie':'WEIBOCN_WM=******************************'
}

測試發現如果不使用Settings裏的Cookie,在spiders文件夾下的爬蟲文件 start_requests函數單獨定義Cookie不好使,登錄微博總是出現401跳轉

  1. Scrapy 項目下創建DBHelper類,用於保存爬蟲數據到數據庫
# -*- coding: utf-8 -*-

import pymysql
from twisted.enterprise import adbapi
from scrapy.utils.project import get_project_settings  #導入seetings配置
import time

table_name = '**********'

class DBHelper():
    '''這個類也是讀取settings中的配置,自行修改代碼進行操作'''

    def __init__(self):
        settings = get_project_settings()  #獲取settings配置,設置需要的信息
        dbparams = dict(
            host=settings['MYSQL_HOST'],  #讀取settings中的配置
            db=settings['MYSQL_DBNAME'],
            user=settings['MYSQL_USER'],
            passwd=settings['MYSQL_PASSWD'],
            charset='utf8',  #編碼要加上,否則可能出現中文亂碼問題
            cursorclass=pymysql.cursors.DictCursor,
            use_unicode=False,
        )
        #**表示將字典擴展爲關鍵字參數,相當於host=xxx,db=yyy....
        dbpool = adbapi.ConnectionPool('pymysql', **dbparams)

        self.dbpool = dbpool

    def connect(self):
        return self.dbpool

    def close(self):
        self.dbpool.close()

    #寫入數據庫
    def insert(self, item):
        sql = "insert into " + table_name + "(blog_short_name,weibo_id,weibo_url,created_at,like_num,repost_num,comment_num,content,user_id,tool,image_url,image_origin_url,video_url,origin_weibo,location_map_info,crawl_time,created_at_date) values(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
        #調用插入的方法
        query = self.dbpool.runInteraction(self._conditional_insert, sql, item)
        #調用異常處理方法
        query.addErrback(self._handle_error)

        return item

    #寫入數據庫中
    def _conditional_insert(self, tx, sql, item):
        # 抓取時間戳
        item['crawl_time'] = time.strftime('%Y-%m-%d %H:%M:%S',
                                           time.localtime(time.time()))
        params = (item['blog_short_name'],item["_id"], item['weibo_url'], item['created_at'],
                  item['like_num'],item["repost_num"], item['comment_num'], item['content'],item['user_id'],item['tool'],item["image_url"],item["image_origin_url"], item['video_url'], item['origin_weibo'],item['location_map_info'], item['crawl_time'], item['created_at_date'])
        
        if (item['created_at_date'] == str(time.strftime("%Y-%m-%d", time.localtime()))) :
            # 判斷微博數據庫是否存在
            query_sql = "select * from " + table_name + " where weibo_id = '" + item["_id"] + "'"
            tx.execute(query_sql)
            query_result = tx.fetchall()
            if query_result:
                print('微博數據庫已存在!!!')
            else:
                print('新微博')
                tx.execute(sql, params)
        else:
            print('不是當天的微博')

    #錯誤處理方法
    def _handle_error(self, failue):
        print(failue)
  1. 實際爬蟲期間,總是報數據連接數量過多(1040 - too many connections),發現爬蟲過程中沒有關閉數據庫連接,在pipelines.py文件中複寫close_spider函數,調用DBHelper的close方法,數據庫連接數量過多的問題就解決了;
class WeiBoPipeline(object):
    # 連接數據庫
    def __init__(self):
        self.db = DBHelper()
    
    def process_item(self, item, spider):
        # 插入數據庫
        self.db.insert(item)
        return item

    def close_spider(self,spider):  #關閉蜘蛛
        self.db.close()
  1. 在Scrapy的settings.py 同目錄下創建一個run_spider.py文件,這裏使用的是CrawlerRunner,而不是CrawlerProcess,因爲使用Process會出現ReactorNotRestartable錯誤
import os
import sys
from scrapy.crawler import CrawlerProcess
from scrapy.crawler import CrawlerRunner
from scrapy.utils.project import get_project_settings

from crochet import setup
def spider_weibo(mode):
    setup()
    settings = get_project_settings()
    runner = CrawlerRunner(settings)
    runner.crawl(*****, 'all')
    runner.join()
  1. Django調用Scrapy,需要在Django創建的APP裏用celery創建一個job,在job裏調用run_spider.spider_weibo(’****’);
  2. 最後用supervisor進程管理,啓動Django,celery,這裏supervisor我用pip安裝的,安裝到了Django的venv中;
[program:supervisor_django]
command=/Project/weixin/venv/bin/python manage.py runserver 0.0.0.0:80

[program:supervisor_celery_worker]
command=/Project/weixin/venv/bin/celery -A djangoWeb worker -l info
 
[program:supervisor_celery_beat]
command=/Project/weixin/venv/bin/celery -A djangoWeb beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
  1. 這裏我使用了django-celery-beat後臺管理的頁面,添加定時任務,如果出現了時區的問題,可是在Django的settings文件裏添加
# 官方用來修復CELERY_ENABLE_UTC=False and USE_TZ = False 時時間比較錯誤的問題;
# 詳情見:https://github.com/celery/django-celery-beat/pull/216/files
DJANGO_CELERY_BEAT_TZ_AWARE = False
  1. 這裏我做了一個前端頁面來顯示爬蟲微博的結果,每隔五分鐘爬一次微博,抓取特定用戶當天發的微博,想觀察效果可以關注公衆號 ----島城窩窩 ,回覆 微博 查看頁面
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章