- 先来张前端页面展示以下爬虫的结果 ,daochengwowo.top
- 搭建Django Server,用Django(Version 3.0)创建一个app,作为爬虫的入口;
项目结构图
- 用Django的Model创建数据库模型,数据库用的是Mysql;
- 跟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跳转
- 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)
- 实际爬虫期间,总是报数据连接数量过多(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()
- 在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()
- Django调用Scrapy,需要在Django创建的APP里用celery创建一个job,在job里调用run_spider.spider_weibo(’****’);
- 最后用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
- 这里我使用了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
10.用Supervisor启动Django,如果把Debug设成False ,会出现找不到静态文件的问题,所以我用Apache启动Django(可以参考我的另一篇文章Apache部署django),Supervisor负责启动Celery.
-
这里我做了一个前端页面来显示爬虫微博的结果,每隔五分钟爬一次微博,抓取特定用户当天发的微博,想观察效果可以关注公众号 ----岛城窝窝 ,回复 微博 查看页面
-
dd