爬虫实战(一)—利用requests、mongo、redis代理池爬取英雄联盟opgg实时英雄数据

in python爬虫 with 0 comment

概述

此篇文章,主要记录利用Python request模块爬取LOL opgg英雄实时数据,并保存到mongodb中,爬取使用了可靠的redis维护IP代理池,这个过程已在腾讯云服务器上完成每日定时爬取,并完成个人订阅号 loak 的查询接口。

爬虫相关:爬虫模块 requests、 mongodb模块 pymongo、 html解析 BeautifulSoup、 正则 re模块、 xml解析 xmltodict

redis代理池:使用了Github IP代理池项目 jhao104/proxy_pool,在centos7完成redis安装、远程登录、密码登录等设置

mongodb:完成在centos7上,Python2的完全卸载及Python3的安装,mongodb的安装、用户管理、远程登录、可视化管理adminMongo配置

微信订阅号:完成微信订阅号 loak 的接口测试、腾讯云服务器用户消息接收、回复、保存

centos7:完成定时任务实现、记录运行日志、多命令一次执行、根据进程名查询进程pid、及杀死进程

BaseException
+-- LOLGokEnv
+-- LOLGokSpider
 +-- Config.py
 +-- LOL
 |    +-- __init__.py
 |    +-- heroClass.py
 |    +-- mongoClient.py
 |    +-- opggSpider.py
 +-- SpiderUtil
 |    +-- __init__.py
 |    +-- hero_another_name.xml
 |    +-- wxUtil.py
 |    +-- xmlUtil.py
 +-- Web
 |    +-- __init__.py
 |    +-- wxWeb.py

爬虫实现

    # 获取英雄列表
    herohtml = requests.get(opgg_config['OPGG_MAIN_URL'], headers=headers, timeout=120, proxy=proxy).text
    # 存储所有英雄的hero对象
    list_hero = []
    soup = BeautifulSoup(herohtml, 'lxml')
    hero_items = soup.find_all(class_='champion-index__champion-item')
    hero_item_version = soup.select_one('[class~=champion-index__version]').text.split(':')[1].strip()

    for hero_item in hero_items:
        hero_en_name = hero_item['data-champion-key']
        hero_cn_name = hero_item['data-champion-name']
        hero_positions_items = hero_item.find_all(class_='champion-index__champion-item__position')
        hero_positions = []
        for hero_position in hero_positions_items:
            hero_positions.append(hero_position.text)
        hero = HeroClass(hero_en_name, hero_cn_name, hero_positions, hero_item_version)
        list_hero.append(hero)

redis维护IP代理池

以下主要是在centos7下的安装、维护。

Python3、Mongodb、adminMongo

     use admin
     db.createUser(
       {
         user: "myUserAdmin",
         pwd: "abc123",
         roles: [ { role: "userAdminAnyDatabase", db: "admin" } ]
       }
     )

重启 MongoDB

  重启并进入控制台,强制使用用户名、密码认证。
  mongod --auth
  mongo
  授权
  use admin
  db.auth("myUserAdmin", "abc123" )

添加数据库用户

   > use test
   switched to db test
   > db.foo.insert( { x: 1, y: 1 } )
   WriteCommandError({
       "ok" : 0,
       "errmsg" : "too many users are authenticated",
       "code" : 13,
       "codeName" : "Unauthorized"
   })

添加用户:

   use test
   db.createUser(
     {
       user: "myTester",
       pwd: "xyz123",
       roles: [ { role: "readWrite", db: "test" },
                { role: "read", db: "reporting" } ]
     }
   )

重新进入控制台,授权、执行插入操作:

      > use test
      switched to db test
      > db.auth("myTester", "xyz123" )
      1
      > db.foo.insert( { x: 1, y: 1 } )
      WriteResult({ "nInserted" : 1 })

微信订阅号接口测试与搭建

        <xml>
        <ToUserName><![CDATA[gh_866835093fea]]></ToUserName>
        <FromUserName><![CDATA[ogdotwSc_MmEEsJs9-ABZ1QL_4r4]]></FromUserName>
        <CreateTime>1478317060</CreateTime>
        <MsgType><![CDATA[text]]></MsgType>
        <Content><![CDATA[你好]]></Content>
        <MsgId>6349323426230210995</MsgId>
        </xml>

因此后台 Python flask代码则如下:

from flask import Flask,request
import hashlib
import xmltodict
import time

app = Flask(__name__)

@app.route('/wx', methods=["GET", "POST"])
def getinput():
    if (request.method == "GET"):
    # 表示是第一次接入微信服务器的验证,验证完之后可以删掉
        signature=request.args.get('signature')
        timestamp=request.args.get('timestamp')
        nonce=request.args.get('nonce')
        token = "maluguang"
        list = [token, timestamp, nonce]
        list.sort()
        sha1 = hashlib.sha1()
        sha1.update(list[0].encode('utf-8'))
        sha1.update(list[1].encode('utf-8'))
        sha1.update(list[2].encode('utf-8'))
        hashcode = sha1.hexdigest()
        echostr = request.args.get("echostr")
        if hashcode == signature:
            return echostr
        else:
            return ""

    elif request.method == "POST": # 这里是验证完后的接受处理用户发送的消息
        # 表示微信服务器转发消息过来
        xml_str = request.data
        if not xml_str:
            return""
        # 对xml字符串进行解析
        xml_dict = xmltodict.parse(xml_str)
        xml_dict = xml_dict.get("xml")

        # 提取消息类型
        msg_type = xml_dict.get("MsgType")
        if msg_type == "text":
        # 表示发送的是文本消息
        # 构造返回值,经由微信服务器回复给用户的消息内容
            resp_dict = {
                "xml": {
                    "ToUserName": xml_dict.get("FromUserName"),
                    "FromUserName": xml_dict.get("ToUserName"),
                    "CreateTime": int(time.time()),
                    "MsgType": "text",
                    "Content": "you say:" + xml_dict.get("Content")
                }
            }

            # 将字典转换为xml字符串
            resp_xml_str = xmltodict.unparse(resp_dict)
            # 返回消息数据给微信服务器
            return resp_xml_str
        else:
            resp_dict = {
                "xml": {
                    "ToUserName": xml_dict.get("FromUserName"),
                    "FromUserName": xml_dict.get("ToUserName"),
                    "CreateTime": int(time.time()),
                    "MsgType": "text",
                    "Content": "Dear I Love you so much"
                }
            }
            resp_xml_str = xmltodict.unparse(resp_dict)
            # 返回消息数据给微信服务器
            return resp_xml_str
if __name__ == '__main__':
    app.run(port='4000')

centos7一些shell脚本

  PIDS=`ps -ef |grep main.py |grep -v grep | awk '{print $2}'`
  if [ "$PIDS" != "" ]; then
    cd /home/LOLGokSpider/LOL && /home/LOLGokEnv/bin/python opggSpider.py > /home/cro_sh/spider.out 2>&1
  else
    cd /home/proxy_pool/ && proxy_pool_env/bin/python Run/main.py
    PIDS=`ps -ef |grep main.py |grep -v grep | awk '{print $2}'`
    if [ "$PIDS" != "" ]; then
    cd /home/LOLGokSpider/LOL && /home/LOLGokEnv/bin/python opggSpider.py
    else
    "error" > /home/cro_sh/proxy_pool_error.out 2>&1
    fi
  fi

缩进语法这些应该是没问题的,就是他一直只运行到 cd /home/proxy_pool/ && proxy_pool_env/bin/python Run/main.py ,并没有开始爬取的进程。

loak订阅号效果

输入:排行 上
可以查询上单的强势英雄、胜率、登场率等
输入:寒冰
查询寒冰在各位置的占比、胜率、登场率
输入:寒冰 ad
查询寒冰在adc位置上的加点、出装、天赋等
关于英雄的名称,可以输入别名,如下的瘟疫之源可以改成老鼠。
在这里插入图片描述

Responses