Python

大乐透数据爬取和网页可视化

Jaydon · 12月8日 · 2019年 · · 365次已读

1.环境:python3.6.5 + windows10

2.依赖包: requests(需安装)、flask(需安装)、fake-useragent(需安装)、pyecharts==0.5.11(需要指定版本安装)

3.数据网址(http://datachart.500.com/dlt/)

一、分析网站

1.打开数据网址,可以看到如下页面

2.查看网页源代码

可以看到每一期的结果就在网页源代码里面,由于这些结果没有用特殊的class属性或者id属性包含着,所以并不方便用网页解析库如pyquery、beautifulSoup这些库去获取数据,这里就采用re正则表达式的库去提取数据

二、编写代码

base_crawler.py

# codong:utf8

import requests
import traceback
import csv
import codecs    # 可用于python2、python3指定写入或打开文件的编码方式
from fake_useragent import UserAgent  # 用来模拟浏览器请求
from multiprocessing.dummy import Pool     # 多线程库,线程池
import string
import random
import os

ua = UserAgent()


class BaseCrawler(object):

    def __init__(self, url):
        self.url = url
        self.headers = {"User-Agent": ua.random}

    def get_web_data(self, method, params="", data="", get_type=1) #根据请求方式、参数等获取网页数据
        try:
            response = requests.request(url=self.url, headers=self.headers, method=method, params=params, data=data, timeout=5)
            print(response.status_code, response.url)
            response.encoding = response.apparent_encoding  # 采用网页的编码方式,避免获取的数据乱码
            if get_type == 1:
                return response.text   # 返回文本字符串
            else:
                return response.json()   # 返回json字符串
        except:
            traceback.print_exc()   # 错误打印
            return

    @staticmethod
    def create_random_str(length=12):    # 随机生成12位长度的字符串
        str_data = string.ascii_letters + string.digits
        return "".join(random.sample(str_data, length))

    def download_mp4(self, url):
        try:
            response = requests.get(url, headers=self.headers)
            data = response.content   # 下载图片、视频都用response.content,表示二进制数据流
            if not os.path.exists("mp4"):
                os.mkdir("mp4")
            filename = os.getcwd()+"/mp4/"+self.create_random_str()+".mp4"
            with open(filename, "wb") as f:
                f.write(data)
        except:
            print("download error!!!")

    def download(self, urls):      # 多线程下载视频,和download_mp4关联
        if not isinstance(urls, list):
            urls = [urls]
        pool = Pool(4)
        pool.map(self.download_mp4, urls)
        pool.close()
        pool.join()

    @staticmethod
    def write_csv(filename, header, data):      # 写入csv表格
        f = codecs.open(filename, "w", encoding="gbk")
        csv_writer = csv.writer(f, dialect='excel')
        csv_writer.writerow(header)
        for i in data:
            csv_writer.writerow(i)
        f.close()

2.get_lottery_data.py

# coding:utf8
from base_crawler import BaseCrawler
import re

CRAWLER_URL = "http://datachart.500.com/dlt/"


def parse_web_data():
    crawler = BaseCrawler(CRAWLER_URL)
    webData = crawler.get_web_data("get")
    if not webData:
        return [], []
    reg = r'<td align="center">\d{5} </td.*?tr>'
    reg1 = r'>(\d{5})'     # 带有括号表示只要括号中的那部分数据
    reg2 = r'chartBall01">(\d+)<|chartBall02">(\d+)<'
    webData = re.findall(reg, webData, re.S)    # 正则匹配查找,返回结果是列表
    items = list()
    result_list = list()
    print("*" * 80)
    for i in webData:
        item = re.findall(reg1, i, re.S)
        result = re.findall(reg2, i, re.S)
        items.extend(item)   # 合并列表
        result_list.append([j[0] if j[0] else j[1] for j in result])
    return items, result_list


if __name__ == '__main__':
    items, result_list = parse_web_data()
    print(result_list)

三、结果展示

可以看到每一期的结果就爬取出来了,下面进行用pyecharts + flask进行数据的可视化

四、数据可视化

1.lottery_data_handler.py(直接运行这个就可以,把爬取数据也结合在一起了)

# coding:utf8
from flask import Flask, render_template
from pyecharts import Line
from base_crawler import BaseCrawler
import re

REMOTE_HOST = "https://pyecharts.github.io/assets/js"
CRAWLER_URL = "http://datachart.500.com/dlt/"

app = Flask(__name__)


def parse_web_data():
    crawler = BaseCrawler(CRAWLER_URL)
    webData = crawler.get_web_data("get")
    if not webData:
        return [], []
    reg = r'<td align="center">\d{5} </td.*?tr>'
    reg1 = r'>(\d{5})'
    reg2 = r'chartBall01">(\d+)<|chartBall02">(\d+)<'
    webData = re.findall(reg, webData, re.S)
    items = list()
    result_list = list()
    for i in webData:
        item = re.findall(reg1, i, re.S)
        result = re.findall(reg2, i, re.S)
        items.extend(item)
        result_list.append([j[0] if j[0] else j[1] for j in result])
    return items, result_list


def handle_data():
    items, result_list = parse_web_data()
    lines = list()
    for i in range(7):     # 一期有七个号码,生成七个号码的数据折线图
        line = Line("体育彩票", "第%s个号码分析" % (i+1))    # 折线图,参数:标题,副标题
        y = [j[i] for j in result_list]   # 生成每一期的第i个号码列表
        line.add(
            "",   # 标签
            items,    # x轴
            y,       # y轴
            is_label_show=True,    # 是否展示折线图的每个数值
            is_more_utils=True,    # 是否展示折线图的工具栏
            is_datazoom_show=True  # 横坐标可以伸缩
        )
        lines.append(line)
    return lines


@app.route("/")
def lottery_data():
    lines = handle_data()
    if not lines:
        return "<h1>数据获取出错</h1>"

    result = dict(
        myecharts=[line.render_embed() for line in lines],
        host=REMOTE_HOST,
        script_list=lines[0].get_js_dependencies()
    )
    return render_template("lottery_data_show.html", **result)


if __name__ == '__main__':
    app.run(debug=True)

2.lottery_data_show.html(这个文件需要放在templates文件夹下)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Awesome-pyecharts</title>
    <script src="https://cdn.bootcss.com/jquery/3.0.0/jquery.min.js"></script>
    <script type="text/javascript" src="https://assets.pyecharts.org/assets/echarts.min.js"></script>
    {% for jsfile_name in script_list %}
        <script src="{{ host }}/{{ jsfile_name }}.js"></script>
    {% endfor %}
</head>
<body>
<div id="bar">
    {% for myechart in myecharts %}
        {{ myechart|safe }}
    {% endfor %}
</div>

</body>
</html>

3.结果展示

4.优化方案

这样直接运行代码,打开网页会有点慢,可以采用redis缓存爬取的数据结果,这里就先不弄了

2 条回应
    三水非冰 Edge 79.0.309.43 Windows 10 2019-12-9 · 20:39

    大佬这两个月更新挺频繁呀,终于记起了博客后台的账号了吗?

    上面代码我拿走去玩了,顺便跟大佬说一声,我博客域名从cn变成了com,有空的时候可以更新一下哈~

      Jaydon 搜狗浏览器 2.X Windows 10 2019-12-11 · 17:29

      有一天突然发现了一个巨漂亮的网站!仔细一看竟然是我自己的!好不容易找到了账号密码。。。终于是登录成功了!