夜樱

记一次简单的爬取可视化
暑假的一次爬虫任务,正好拿来练练手顺便治治自己平时不怎么写代码的懒癌。目前现在python爬虫的第三方库越来越多也...
扫描右侧二维码阅读全文
06
2019/08

记一次简单的爬取可视化

暑假的一次爬虫任务,正好拿来练练手顺便治治自己平时不怎么写代码的懒癌。目前现在python爬虫的第三方库越来越多也比较强大,最主要还是python简洁易懂的语法和强大的第三方库使得python变成了最大众化的一个编程语言,原因就是易上手。

头图地址:流星-ナコモ

任务目标

  • 爬取http://www.animeshow.tv/下的full anime list的动漫列表
  • 获取动漫信息并存储(存储格式不限,可以txt,数据库,json格式等等)
  • 必须要有的数据(动漫名称,动漫地址,类型,播出时间,状态,流派,摘要)
  • 把存储后的数据调用显示在前端界面上,采用图表方式做可视化呈现

工程结构:
工程结构.png

目标分析

进入网页后根据观察,动漫以分类方式排序,用开发者工具选择工具移动到动漫名字上,看到开发中工具中定位到了该标签的内容,是以一个a标签做的链接

寻找子页面的链接.png

点进去后则是该部动漫的具体介绍信息

内容.png

我们根据要求,里面的type,Year等信息都是我们需要的需要将其过滤出来整理,python中可以用Beatifulsoup来进行标签定位获取,这边我自己是用了正则表达式过来获取

代码过程

爬虫py文件:

import re,requests,os   #导入正则,requests,os库
from openpyxl import workbook    #导入用于写入excel的库
from multiprocessing import Process    #多进程的库
URL = "http://www.animeshow.tv/anime-list.html"     #设置目标网页
html = requests.get(URL).text       #获取目标网页内容并转为文本
links = re.compile('href="(.+?)"')   #编译正则匹配所有href里的字符串内容
link = links.findall(html)           #利用正则findall寻找编译的正则表达式
link_list = link[38:]              #筛选出有用的番剧链接信息
#正则模块
Types = re.compile("Type: .*?<div>(.+?)</div>")   #匹配类型内容
Summary_re = re.compile('<p>(.*?)</p>')           #匹配介绍内容
Year_re = re.compile('Year:.*?<div>(.*?)</div>')    #匹配日期内容
Status_re = re.compile('Status:.*?<div>(.*?)</div>')    #匹配状态内容
Genres_re = re.compile('Genres:.*?<a href=".*?">(.*?)</a>') #匹配流派内容
title_re = re.compile('<title>(.*?) - AnimeShow.tv</title>')    #匹配标题内容

list_month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']#月份表
Jan = Feb = Mar = Apr = May = Jun = Jul = Aug = Sep = Oct = Nov = Dec = 0
month_data = [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec]
#打引统计好的值用于填入可视化
def time_range():
    for i in range(0,12):
        if Year[0:3] == list_month[i] :
            month_data[i] += 1
#爬取以及写入模块
def data_get():
    global title, Type, Summary, Year, Status, Genres
    x = 0
    TV_Series = Movie = OVA = Special = 0

    wb = workbook.Workbook()  # 创建Excel对象
    ws = wb.active  # 获取当前正在操作的表对象
    ws.append(["Status", "title", "Type", "Year", "Genres", "Summarys"])  # 往表中写入标题行,以列表形式写入
    for i in link_list:
        cartoon_html = requests.get(i).text     #获取子网页html文本内容
        # 这里利用正则匹配后的列表数据转化成字符串
        Type = "".join(Types.findall(cartoon_html))
        Summarys = Summary_re.findall(cartoon_html)
        Summary = "".join(Summarys[1:len(Summarys)-2])
        Year = "".join(Year_re.findall(cartoon_html))
        Status = "".join(Status_re.findall(cartoon_html))
        Genres = "".join(Genres_re.findall(cartoon_html))
        title = "".join(title_re.findall(cartoon_html))
        #输入内容到控制台
        print(title,"\n",Type,"\n",Summary,"\n",Year,"\n",Status,"\n",Genres,"\n")
        #向Execl写入以行形式写入数据
        ws.append([Status,title,Type,Year,Genres,Summary])
        time_range()

        if Type[0:9] == "TV Series":
            TV_Series += 1
        elif Type[0:5] == "Movie":
            Movie += 1
        elif Type[0:3] == 'OVA':
            OVA += 1
        elif Type[0:7] == "Special":
            Special += 1
        print("爬取完成进度:{:.2%}".format(x / 1226))     #以进度表示完成度
        print("TV Series:"+str(TV_Series),"Movie:" + str(Movie),'OVA:'+str(OVA),"Special:"+str(Special))
    x += 1

-

    print("[INFO]: 100%爬取结束")
    print("一月:" + str(month_data[0]), "二月:" + str(month_data[1]), 
          "三月:" + str(month_data[2]), "四月:" + str(month_data[3]), 
          "五月:" + str(month_data[4]),"六月:" + str(month_data[5]),
          "七月:" + str(month_data[6]), "八月:" + str(month_data[7]), 
          "九月:" + str(month_data[8]), "十月:" + str(month_data[9]), 
          "十一月:" + str(month_data[10]),"十二月:" + str(month_data[11]))
    wb.save('anime.xlsx')#保存爬取数据并关闭
        
    #编译成json格式写入json文件
    dictionary = dict(zip(list_month, list_month2))
    print(dictionary)
    data = json.dumps(dictionary)
    with open("data.json","wb") as file:
        file.write(data.encode())
#进程化运行模块
def run_proc1(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))
    print(data_get(),"\n")

#以进程形式运行
if __name__ == '__main__':
    print('Parent process %s.' % os.getpid())
    p1 = Process(target=run_proc1, args=('spider',))     #创建进程
    print('Child process will start.')
    p1.start()   #进程启动
    p1.join()   #添加任务
    print('Child process end.')    #进程结束

Flask的py主文件:

from flask import Flask    #导入Flask模块
from flask import render_template        #导入渲染模板模块
import json

#读取json文件并分成列表,以便传值
with open("data.json","r") as  f:
    js = f.read()
    js = json.loads(js)
month ,data = list(js.keys()),list(js.values())

app = Flask(__name__) #主入口

@app.route('/')  #路由
def index():
    return render_template('index.html',data=data,month=month)#渲染模板以及传参

if __name__ == '__main__':
   app.run()  #运行在本地环境,如需配置请设置host="xxxxx",port=xxxx

爬取结束写入文件后的效果

爬取效果.png

可能会看到在介绍那边会有一点标签<p>字符残留

再看看这个造成这个原因的html结构

标签残留.png

这个原因是因为正则在匹配表达时候其中一个标签出现了空内容,正则表达式则会把最先前匹配到的给写入进去造成,也可以自己后面提取出来去掉再放到列表

可视化部分

因为这边数据不是经常变动而且比较固定,所以部分选择了统计数量后填写静态数据展示

可视化工具使用了百度的Echarts,具体的实例Echarts即可找到配置方法,这里就不再讲述直接看效果

利用Flask的框架进行搭建web,通过jinja2模板进行传值

传值.png

运行flask后即可访问地址观看效果

开发工具.png

展示.png

最后我将他放在了云机上展示,展示地址为 Anime可视化展示

END

说实在自己代码水平真的很不行,平时也练的很少从上面代码看下来都是一些很死脑筋写出来的,但还是学习到了一些知识,最重要的还是正则吧,会写正则真的方便太多了。再则跟身边同龄人比差距还是太大了,代码这样的东西还是多写才会好。

也就当暑假里完成的一个小任务

Last modification:August 7th, 2019 at 03:06 pm
If you think my article is useful to you, please feel free to appreciate

2 comments

  1. ⑨BIE

    正则大法吼,贪婪模式一把梭|´・ω・)ノ

    1. 小萌羽
      @⑨BIE

      一梭子下去我死了

Leave a Comment