美文网首页
qqbot结合scrapy爬虫框架、图灵api实现自己的qq机器

qqbot结合scrapy爬虫框架、图灵api实现自己的qq机器

作者: Garwer | 来源:发表于2018-12-22 00:59 被阅读0次

    写在前面

    利用Scrapy框架爬取笑话,之后再用qqbot机器人每天都给自己发笑话,给自己发最近的热门电影,想想还挺有趣的,既然有想法,实践就很重要。

    但是这篇博客快写完了的时候我才注意到一个灰常坑的地方。。

    jpg

    就是qqbot,即将停止smartqq,可能写了明年就用不了了【qqbot基于smartqq协议,即以前的webqq】,这只剩下几天了,所以感觉做了这个也没啥卵用。。但是爬虫的部分后面还是可以用得到。

    大致思路

    1.搭建需要的模块、数据库环境

    2.用scrapy爬取web上的数据【如热门电影,搞笑笑话等等】

    3.将爬取回来的数据存到数据库中

    4.用qqbot针对不同场景、对不同的人/群发送特定消息【比如发送笑话相关,返回爬虫的笑话数据,发送电影相关返回最近的热门电影。使用图灵机器人等api动态实现qq机器人效果等等】

    5.部署至服务器上,放在linux上,需考虑环境的部署,和scrapy抓取任务定时执行,qqbot后台运行等等。。

    爬虫框架Scrapy安装及使用文档

    windows环境

    pip install Scrapy
    

    切换为国内的清华源【速度为比较快】 如果需要代理访问外网 则在pip后加上--proxy ip:port

    pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    切换为清华源【如果需要代理 在install前加 —proxy ip:port】

    #此处ip:端口使用本地的代理
    pip install scrapy -i https://pypi.tuna.tsinghua.edu.cn/simple
    

    如果报错

    building 'twisted.test.raiser' extension
    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools
    

    就是根据自己的版本号手动安装所需工具,之后再安装scrapy

    pip install C:\Users\LJW\Downloads\Twisted-18.9.0-cp36-cp36m-win_amd64.whl
    
    #创建
    scrapy startproject scrapyApp
    

    运行过程中报

    ModuleNotFoundError: No module named 'win32api'
    

    安装地址 下载地址 选择合适自己的版本并安装

    推荐使用aconda,会帮忙安装依赖,不用因为环境一直折腾。。

    MAC环境

    mac下安装相对简单,缺少了上述几个报错的依赖,这边用如果用Anaconda搭建环境更为容易,关于Anaconda,

    下载地址

    下载完后,为了方便以后安装依赖工具,这边先设置下代理

    #设置清华的conda镜像源
    conda config --add channels https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
    
    #设置搜索时显示通道地址
    conda config --set show_channel_urls yes
    
    #查看当前镜像源地址
    sudo vim ~/.condarc
    
    #或者
    conda config  --show-source
    

    利用conda下载模块

    conda install xxx
    

    如果报错

    The following packages are not available from current channels
    

    则使用pip,参考

    #利用conda安装scrapy
    conda install scrapy
    
    #创建scrapy爬虫项目,这边先到pycharm项目下 
    scrapy startproject scrapyApp
    
    #执行该项目
    scrapy crawl scrapyApp
    

    pycharm使用conda环境

    首先用aconda创建一个python环境【这边我增加了一个名为scrapy、python版本为3.7的环境】,这边直接在应用程序里添加环境【也可以在终端使用命令,参考linux部署方式】

    添加环境后,在pycharm设置为刚才创建名为scrapy的环境。

    scrapy

    在相应的环境安装好scrapy后,先编写一个灰常简单例子,测试爬取我的博客的标题

    先创建项目,在pycharm项目的目录下

    scrapy startproject scrapyApp
    #执行后会自动生成下图目录结构图
    

    简单例子

    生成目录结构后,在spiders下的scrapyApp.py下编写简单测试。源码如下

    # -*- coding: utf-8 -*-
    import scrapy
    
    class itemSpider(scrapy.Spider):
        print('=======开始爬取======')
    
        #这边注意名称需保持一致
        name = "scrapyApp"
    
        start_urls = ['https://www.garwer.cn/']
    
        def parse(self, response):
            # 获取网站标题
            context = response.xpath('/html/head/title/text()')
            # 提取网站标题
            title = context.extract_first()
            print('==================标题=================:' + title);
            pass
    

    控制台输入scrapy crawl scrapyApp后可以看到成功爬取到博客的标题

    爬取最近热门的电影

    刚刚的例子非常入门,甚至都用不到scrapy组件自动生成的items.py、pipelines.py等脚本。

    这边以爬取猫眼电影【http://maoyan.com/board/7】,为例【因为页面比较简单】,

    初步观察,口碑班、期待版分别为【7,6,1,2,4】

    这边主要爬取各个榜单的关键几个信息【排行、标题、演员、上映时间】

    准备工作

    配置文件修改:

    修改自动生成的settings.py文件

    1.修改ROBOTSTXT_OBEY的配置为False【不遵循规则】

    2.添加以下

    HTTPERROR_ALLOWED_CODES = [403] #设置允许403
    USER_AGENT = 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36'
    FEED_EXPORT_ENCODING = 'gbk'
    

    1.观察该网站

    2.定义要爬取项

    在自动生成items.py定义要爬取项的域

    import scrapy
    #要爬取的数据 【排行、电影名、演员、上映时间、评分】
    class ScrapyappItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        top = scrapy.Field()
        title = scrapy.Field()
        star = scrapy.Field()
        releasetime = scrapy.Field()
        type = scrapy.Field
        pass
    

    3.爬取电影数据

    scrapy爬取数据主要通过编写Spider类来完成。items只是定义用的,每个项具体包在什么样的html标签内需要观察爬取。

    查看网页结构,根据结构进行爬取所需内容【这边评分分两块区域,而且不再movie-item-info下暂时还不知道怎么爬取】

    scrapyApp.py源码

    # -*- coding: utf-8 -*-
    import scrapy
    from scrapy.http import Request
    from scrapy.selector import Selector
    
    #引入项目
    from scrapyApp.items import ScrapyappItem
    
    class itemSpider(scrapy.Spider):
        print('=======开始爬取猫眼电影数据======')
    
        #这边注意名称需保持一致
    
        name = "scrapyApp"
        pagelist = [7, 6, 1, 2, 4]
    
        def start_requests(self):
            for i in self.pagelist:
                self.url = 'http://maoyan.com/board/{page}'.format(page=i)
                yield Request(self.url, callback=self.parse)
    
        #根据h5标签获取要爬取的内容
        def parse(self, response):
            item = ScrapyappItem()
            selector = Selector(response)
            #navbar 为菜单栏 获取激活的标题 类似['榜单', '最受期待榜']格式 -1为取后面的
            active = selector.xpath('//ul[@class="navbar"]/li/a[@class="active"]/text()').extract()
            #dd元素为top 获取排行榜
            tops = selector.xpath('//dd/i/text()').extract()
            movies = selector.xpath('//div[@class="movie-item-info"]')
            #遍历电影信息
            for i, content in enumerate(movies):
                title = content.xpath('p[@class="name"]/a/text()').extract()
                star = content.xpath('p[2]/text()').extract()
                releasetime = content.xpath('p[3]/text()').extract()
                item['top'] = tops[i] #排行
                item['title'] = title[0]
                #演员 去空格
                item['star'] = star[0].replace(' ', '').replace('\n', '')
                item['type'] = str(active[-1]) #类型
                if releasetime:
                    item['releasetime'] = releasetime[0].replace(' ', '').replace('\n', '')
                else:
                    item['releasetime'] = ''
                yield item
    

    4.执行该爬虫项目引擎

    #先进入之前创建的conda环境,执行以下[scrapyApp项目]
    scrapy crawl scrapyApp
    

    执行结果

    5.存入数据库【mysql】操作

    已经能够爬取到数据后,接下来就是存入数据库做持久化操作,这边以操作mysql为例,先进入刚才设置的conda环境【命名为scrapy】。

    pip install pymysql
    

    可以看到,利用python操作数据库可以说是非常简便的。

    进入正题,下面将爬取回来的数据存入mysql中

    先建一张存放数据的表maoyan_movie

    DROP TABLE IF EXISTS `maoyan_movie`;
    CREATE TABLE `maoyan_movie` (
      `movie_id` int(11) NOT NULL AUTO_INCREMENT,
      `top` int(11) DEFAULT NULL,
      `movie_title` varchar(255) DEFAULT NULL,
      `movie_star` varchar(255) DEFAULT NULL,
      `releasetime` varchar(255) DEFAULT NULL,
      `movie_type` varchar(255) DEFAULT NULL,
      PRIMARY KEY (`movie_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
    
    SET FOREIGN_KEY_CHECKS = 1;
    

    mysqlUtil工具类

    import pymysql as mysql
    import config
    
    class DB():
        def __init__(self):
            cfg = config.mysql
            print(cfg['charset'])
            conn = mysql.connect(host= cfg['host'],
                                 port = cfg['port'],
                                 user = cfg['user'],
                                 passwd = cfg['passwd'],
                                 db = cfg['db'],
                                 charset = cfg['charset'])
            self.conn = conn
        def getCon(self):
            return self.conn
    
        def switchType(argument):
            switcher = {
                'now': "热映口碑榜",
                'top100': "TOP100榜",
                "cn": "国内票房榜",
                'usa': "北美票房榜",
                "will": "最受期待榜"
            }
            return switcher.get(argument, "nothing")
    
        #获取最近热门top10
        def getTop10(self, type):
            # 创建游标
            cursor = self.conn.cursor()
            rows = []
            # 执行sql 并返回受影响的行数
            switcher = {
                'now': "热映口碑榜",
                'top100': "TOP100榜",
                "cn": "国内票房榜",
                'usa': "北美票房榜",
                "will": "最受期待榜"
            }
    
            flag = switcher.get(type, "nothing")
            sql = 'select top, movie_title, movie_star,releasetime from maoyan_movie t where t.movie_type =  "'+flag+'" order by top'
            print(sql)
            cursor.execute(sql)
            results = cursor.fetchall()
            for row in results:
                title = str(row[0]) + ':' + str(row[1]) + ',' + str(row[2]) + ',' + str(row[3])
                rows.append(title)
            print(rows)
            self.conn.close()
            return rows
    
    
    #DB().getTop10('top100');
    

    这边用到pipelines.py

    首先先在settings.py注册pipelines.py中的ScrapyappPipeline类

    ITEM_PIPELINES = {
        'scrapyApp.pipelines.ScrapyappPipeline': 300,
    }
    

    注册后开始编写pipelines.py

    源码如下

    # -*- coding: utf-8 -*-
    
    # Define your item pipelines here
    # 将定义
    # Don't forget to add your pipeline to the ITEM_PIPELINES setting
    # See: https://doc.scrapy.org/en/latest/topics/item-pipeline.html
    
    #将爬取到的数据存取到数据库
    import pymysql as mysql
    import mysql_model.mysqlUtil as mysqlUtil
    
    
    class ScrapyappPipeline(object):
        def __init__(self):
            self.conn = mysqlUtil.DB().getCon()
            # self.conn = mysql.connect(host='127.0.0.1',
            #                      port=3306,
            #                      user='root',
            #                      passwd='linjiawei',
            #                      db='actApp',
            #                      charset='utf8')
            #通过cursor执行增删改查
            self.cursor = self.conn.cursor()
    
            self.cursor.execute("truncate table maoyan_movie")
            #每次初始化前先删掉maoyan_movie【一次5个榜单十个排行50条记录】
            self.conn.commit()
        def process_item(self, item, spider):
            try:
                print(item['star'])
                self.cursor.execute("""insert into maoyan_movie(top, movie_title, movie_star,releasetime,movie_type)
                                  values (%s,%s,%s,%s,%s)""",
                                      (item['top'], item['title'], item['star'], item['releasetime'], item['type']))
                self.conn.commit()
            except mysql.Error:
                print("===存储发生错误===")
                print("Error%s,%s,%s,%s" % (item['top'], item['title'], item['star'], item['releasetime']))
            return item
    

    之后再执行

     scrapy crawl scrapyMaoyan
    

    之后查看数据库表记录,5个不同榜单数据已记录在数据库中

    qqbot

    按照以上方式安装qqbot后,这边conda install qqbot不清楚为什么失败,可能是源没有,后用 pip install qqbot成功安装。

    qqbot即qq机器人,是腾讯开源出来的一种用python实现的工具,基于smartQQ协议【网页端,不影响手机PC客户端的使用】,可运行在多种平台下。

    成功安装后,在终端输入qqbot,PC端会弹出一个二维码图片,通过扫描二维码即可实现登录,可以在终端上查看自己发的、接受到的消息。如图所示:

    image.png

    常用命令

    #执行qqbot扫完二维码后,不要关闭原有窗口,新建一个终端窗口
    
    # 列出所有好友
    qq list buddy
    
    # 列出 名称 为 xxx 的群
    qq list group xxx
    
    # 列出备注名为 jack 的好友
    qq list buddy mark=jack
    
    # 列出 群“456班” 的所有成员
    qq list group-member 456班
    
    # 列出 群“456班” 中名片为 “mike” 的成员
    qq list group-member 456班 card=mike
    
    # 列出 讨论组“XX小组” 中名为 jack 的好友
    qq list discuss-member XX小组 jack
    

    比如查看备注名为景彪的好友

    向景彪发消息

    qq send buddy 景彪 晚上好啊
    

    代码实例【实现自己的QQ机器人】

    # -*- coding: utf-8 -*-
    from qqbot import QQBotSlot as qqbotslot, RunBot
    
    @qqbotslot
    def onQQMessage(bot, contact, member, content):
        if content == '-hello':
    
            bot.SendTo(contact, '你好,我是QQ机器人')
        elif content == '在':
            bot.SendTo(contact, '我一直在呢,嘻嘻')
    
    
        elif content == '-stop':
    
            bot.SendTo(contact, 'QQ机器人已关闭')
            bot.Stop()
    
    
    if __name__ == '__main__':
        RunBot()
    
    

    执行该py文件后,扫描二维码登录自己的qq

    【这边我用小号测试】 如果其他人发送指定内容,可回复指定内容

    详细参考qqbot github文档

    如果执行时遇到如下错误

    修改/anaconda3/envs/scrapy/lib/python3.7/site-packages/qqbot/qcontactdb路径下 【自己所用py环境qqbot下,http改为https】

    改为https://s.web2.qq.com/api/get_group_name_list_mask2

    参考:第7次请求异常。。。

    qqbot+图灵机器人打造真正的qq机器人

    真的要写一个机器人那太难了,涉及太多算法和语言库,好在有开源的机器人工具和api供我们使用,这里使用图灵机器人来帮助我们做到自动回复的效果。

    图灵机器人官网,需注册账号,获取到自己的apikey,这边还是用免费版测试用

    调用图灵机器人接口,其实就是个restful接口

    之后放在qqbot中,可以对指定人/群,发送接口返回的结果。

    tuling.py

    import requests
    import traceback
    apiKey = "af2979582c864c7ab7865cxxxxx" #注意用自己的
    userid = "641084049"
    #通过msg获取回复消息
    def getMsg(msg):
        apiUrl = "http://www.tuling123.com/openapi/api"
        params = {
            "key": apiKey,#申请到的本接口专用的apiKey
            "info": msg, #要发送给机器人的内容,不要超过30个字符
            "userid": userid   #自定义唯一 userid(1-32位,字母与数字组成),可以识别上下文,比如说我多次发送你好吗,机器人会回复"你好像个复读机呀"之类的信息
        }
    
        try:
            res = requests.post(apiUrl, data=params).json()
            print(res)
            return res.get('text')
        except Exception:
            #打印异常信息
            print("接口调用异常" + traceback.print_exc())
            return
    
    #测试
    getMsg("你好吗")
    
    

    处理消息

    # bot.isMe判断是否为自己发的消息
    if not bot.isMe(contact, member) and g1 is not None:
        if content.find("鸭子") != -1:
            bot.SendTo(contact, "嘎嘎嘎嘎嘎")
        else:
            res = tuling.getMsg(content)
            bot.SendTo(contact, res)
    

    代码初步编写完成后,在mac/win端测试通过后,有几个新的问题来了

    1.想24小时在线,这个时候需要把项目搭在服务器上

    2.linux需也有环境【qqbot、scrapy、redis等等】,而且pc端用python3编写,python版本环境也需一致

    qqbot整合爬虫回来的数据

    比如好友或在群里【指定群】有人发送 "最新电影",返回最近最热门的10部电影,这个时候只需从数据库取回从猫眼爬取回来的热门榜单电影即可。

    代码实现

    先写个mysql查询数据的工具类

    import pymysql as mysql
    import config
    
    class DB():
        def __init__(self):
            cfg = config.mysql
            print(cfg['charset'])
            conn = mysql.connect(host= cfg['host'],
                                 port = cfg['port'],
                                 user = cfg['user'],
                                 passwd = cfg['passwd'],
                                 db = cfg['db'],
                                 charset = cfg['charset'])
            self.conn = conn
    
        def switchType(argument):
            switcher = {
                'now': "热映口碑榜",
                'top100': "TOP100榜",
                "cn": "国内票房榜",
                'usa': "北美票房榜",
                "will": "最受期待榜"
            }
            return switcher.get(argument, "nothing")
    
        #获取最近热门top10
        def getTop10(self, type):
            # 创建游标
            cursor = self.conn.cursor()
            rows = []
            # 执行sql 并返回受影响的行数
            switcher = {
                'now': "热映口碑榜",
                'top100': "TOP100榜",
                "cn": "国内票房榜",
                'usa': "北美票房榜",
                "will": "最受期待榜"
            }
    
            flag = switcher.get(type, "nothing")
            sql = 'select top, movie_title, movie_star,releasetime from maoyan_movie t where t.movie_type =  "'+flag+'" order by top'
            print(sql)
            cursor.execute(sql)
            results = cursor.fetchall()
            for row in results:
                title = str(row[0]) + ':' + str(row[1]) + ',' + str(row[2]) + ',' + str(row[3])
                rows.append(title)
            print(rows)
            self.conn.close()
            return rows
    
    
    #DB().getTop10('top100');
    

    qqbot中调用该方法,完整代码如下,包含定时任务等等。。

    # -*- coding: utf-8 -*-
    import qqbot
    from qqbot import QQBotSlot as qqbotslot, RunBot
    from qqbot import qqbotsched
    import qqbot_model.tuling as tuling
    import pymysql as mysql
    import mysql_model.mysqlUtil as mysqlUtil
    
    @qqbotslot
    def onQQMessage(bot, contact, member, content): #注意content和contact
    
        if content == '-hello':
            bot.SendTo(contact, '你好,我是QQ机器人')
    
        elif content == '在':
            bot.SendTo(contact, '我一直在呢,嘻嘻')
    
        #如果是好友发送-stop 则关闭机器人
        elif content == '-stop' and contact.ctype == 'buddy':
            bot.SendTo(contact, 'QQ机器人已关闭')
            bot.Stop()
    
    
        #如果类型为群 buddy/group/discuss ,代表 好友/群/讨论组 对象
        elif contact.ctype == 'group':
            #g1 = bot.List('group','茶景坊')
            g2 = bot.List('group', 'qqbot测试')
            #如果为这个群 且不为自己发的消息
            #当本qq发消息时,qqbot也会收到一条同样的消息【可能是因为手机端pc端不影响】
            # bot.isMe判断是否为自己发的消息
            if not bot.isMe(contact, member) and g2 is not None:
                if '@ME' in content:
                    bot.SendTo(contact, member.name + ',艾特我干神马呀?')
                if content.find("鸭子") != -1:
                    bot.SendTo(contact, "嘎嘎嘎嘎嘎")
                if content.find("老福") != -1:
                    bot.SendTo(contact, "呱呱呱")
                elif content.find("电影") != -1:
                    type = 'now'; #默认新电影
                    if(content.find("新")):
                        type = "now"
                    elif(content.find("将")):
                        type = "will"
                    elif(content.find("北美")):
                        type = "usa"
                    #以此类推...
                    obj = mysqlUtil.DB()
                    msg = obj.getTop10(type)
                    bot.SendTo(contact, str(msg))
                else:
                    pass
                    #res = tuling.getMsg(content)
                    #bot.SendTo(contact, res)
    
    
        #定时任务 11:55 
        @qqbotsched(hour='11', minute='55')
        def mytask(bot):
            gl = bot.List('group', '上古IOD九大名剑')
            if gl is not None:
                for group in gl:
                    bot.SendTo(group, '同志们:开饭啦啦啦啦啦啦!!!,下午去哪里吃啊!')
    
    
    if __name__ == '__main__':
        RunBot()
    

    实际效果

    部署在linux服务器上

    到现在为止差不多基本的雏形已经有了。

    这边在清华开源软件站下载linux版的conda

    下载地址,也可以选择在conda官网下载

    这边我想过用conda搭建环境,也想过使用docker,跟服务器本地python环境做隔离【最终目的都是为了隔离python环境不影响到本地】

    使用conda部署

    #将下载完成的文件传到新建的用户下
    #新建python用户
    useradd conda
    
    #对此用户设置密码
    passwd conda
    
    #注意
    后续操作如果出现 sudo操作后报以下错误
    conda is not in the sudoers file.  This incident will be reported.
    
    #此时要做添加权限操作 先切换到ROOT用户下 添加文件写权限
    chmod u+w /etc/sudoers
    
    #编辑sudoers文件
    vi /etc/sudoers
    
    #找到root ALL=(ALL) ALL 在下面添加
    conda ALL=(ALL) ALL
    
    #wq保存后撤销sudoers文件写权限
    chmod u-w /etc/sudoers
    
    #之后conda用户就可以用sudo获取权限执行了
    

    安装过程一直回车

    如果报错 Anaconda3-5.3.1-Linux-x86_64.sh: line 353: bunzip2: command not found

    执行 sudo yum install -y bzip2

    安装完成后配置环境变量

    #打开bashrc
    vim ~/.bashrc
    
    #添加以下配置  anaconda3文件夹为安装后自动生成的
    export PATH=/home/conda/anaconda3/bin:$PATH
    
    #保存该配置
    source vim ~/.bashrc
    
    #之后查看是否配置好环境变量 查看当前版本
    conda --v
    
    #这个时候在该用户下会发现python环境跟conda一样为3.7
    

    部署conda环境后,接下来就是新建自己的python环境了

    #创建py版本为3.6,名为py36的环境
    conda create -n py36 python=3.6
    
    #查看当前有的环境列表
    conda env list
    
    #激活环境后
    source activate py36
    
    #激活后进入 python版本为刚才搭的3.6
    #退出环境
    source deactivate
    
    #如果要删除该环境[删除需谨慎]
    conda remove -n py37 --all
    

    进入后, 安装后续需要的相关依赖,安装上面说的方法配置镜像源后【为了更快】

    conda install scrapy
    pip install qqbot  #不知道为什么conda install报错 用了pip
    conda install pymsql
    

    更多参考使用conda隔离python环境

    qqbot相关

    qqbot的配置文件在~/.qqbot-tmp目录下,部署至linux上有几处需做修改

    1.原来执行的时候会占用着终端,需改为后台执行的方式
    2.用服务器方式来启动
    3.设置自动重新登录
    

    将项目整合并ftp至服务器上

    将爬虫项目和qqbot整合一起,传到远程服务器上【conda用户下】,需穿在qqbot的plugins目录下,整合后的目录结构如下。

    qqbot在服务器上启动不像平时在pc端运行脚本,而是先启动qqbot,再把自己的脚本以插件的形式加载到内部

    #临时切换源
    export PATH=$PATH:/home/conda/anaconda3/envs/py36/bin
    
    #启动 这边启动的时候报了参考:[第7次请求异常。。。]参考上面的解决方式
    qqbot -u somebody 
    
    #加载自定义插件
    qq plug qq
    
    
    出现问题的话看启动日志,在.qqbot-tmp下一般以daemon-qq.log命名
    

    mysql相关

    此处本人采用docker安装。

    可参考之前写过的一篇博客 https://www.jianshu.com/p/8dda158dd6e5

    说明:创建端口3308 一个数据库名为garwer 密码为garwer【默认用户还是root】挂载目录为/usr/local/mysql-docker/data的mysql容器【如果需要远程连接,有防火墙的话需设置,这里我是阿里云还需在安全组那边开放3308端口】

    docker run -d -p 3308:3306 --name garwer-mysql --privileged=true -e MYSQL_ROOT_PASSWORD=garwer -e MYSQL_DATABASE=garwer -v /usr/local/mysql-docker/data:/var/lib/mysql mysql:5.7
    

    py程序中也需更改具体mysql相关地址配置改为当前服务器的相关配置。将表结构导入到此环境。

    config.py修改为自己的mysql配置

    #测试爬虫是否可以正常运行
    
    #切换到conda用户
    su - conda
    
    #临时conda中名为py36的源【因为这里我qqbot和scrapy都装在该环境】
    export PATH=$PATH:/home/conda/anaconda3/envs/py36/bin
    
    #执行爬虫任务
    scrapy crawl scrapyApp
    

    通过navicat查到保存到了远程数据库里

    image.png

    定时爬虫任务

    由于猫眼电影数据时实时刷新【每天10点】的,而且数据也不大,可以设置scrapy定时爬取任务

    这边定时有多种办法,比如

    1.使用linux定时任务命令crontab
    2.使用python的time
    3.使用scrapy自带的定时方法
    

    这里我使用1的方式[考虑到比较容易获取到日志信息],其它的还未试过

    crontab参考: https://www.jianshu.com/p/d93e2b177814

    常用命令

    #查看crond任务 如果出现not found说明还未安装 [没安装的话yum install crontab]
    crontab -l
    
    #启动crontab服务
    sudo service crond start
    

    难点

    由于环境部署在conda中名为py36的源上,因此定时任务需先切换到该源然后执行任务

    解决方案【先切换到环境再执行任务】

    #查看当前环境变量
    echo $PATH
    #临时设置环境变量
    export PATH=$PATH:/home/conda/anaconda3/envs/py36/bin
    

    如果要永久设置 还是得修改vi /etc/profile并source /etc/profile【这里就没什么必要了】

    定时任务脚本scrapy.sh

    #0 5 * * * /root/bin/backup.sh 每天8点执行 这边需提前建好logs目录
    #! /bin/sh
    export PATH=$PATH:/home/conda/anaconda3/envs/py36/bin
    # 跳转至Scrapy项目目录
    cd /home/conda/.qqbot-tmp/plugins/scrapyApp
    # 后台运行抓取,并将日志输出到scrapyApp.log文件
    nohup scrapy crawl scrapyApp >> logs/scrapyApp.log 2>&1 &
    

    测试执行

    image.png

    放到定时任务中执行

    # 添加或更新crontab中的命令 回弹出一个文本 在里面输入定时任务命令
    crontab -e
    
    # 每天中午12点执行爬虫任务
    0 12 * * * /home/conda/.qqbot-tmp/plugins/scrapyApp/scrapy.sh
    

    即每天12点都会定时执行爬虫任务

    自此完毕


    总结

    其实整合这几个仔细想想可以做出挺多好玩实用的东西,也考虑过爬取更多的资源、比如笑话、天气预报等待、使用redis将数据缓存起来、将资源用pycharts数据可视化、使用docker部署等等。但时间精力有限,而且python刚学不久,写的有点抠脚, 所以先写了个小项目尝鲜,后续将发布在自己的github上。

    有点坑的地方:

    qqbot有时候发消息延迟有点厉害,详见qqbot官方github文档

    参考链接

    scrapy爬虫框架入门实例

    相关文章

      网友评论

          本文标题:qqbot结合scrapy爬虫框架、图灵api实现自己的qq机器

          本文链接:https://www.haomeiwen.com/subject/ujvbkqtx.html