Python专题

2018-09-30鱼C论坛作品展示分析(超长篇)

2018-09-30  本文已影响213人  右哼哼丨左哼哼

其实呢,当初学习python的时候,我是跟着小甲鱼老师的视频入门的,现在做爬虫.似乎当初学校学C语言的时候,我也上过鱼C论坛,真是满满的回忆啊,也越发感觉小甲鱼真的是无所不能(掰着手指数数吧,C,Python,Web前端,Linux,Java,汇编.....斗尊强者,恐怖如斯!)


近来逛着论坛,看着数不胜数的求问贴,讨论帖,展示贴,资源帖


QQ截图20180930162040.png

就突然想看看这些年哪些人是真正在学习的道路上不断的进步,
同时把自己的所见所得分享给他人的,
由于论坛已经自己有了求问题满意答案的排行榜,这个我就不分析了,我打算找找作品展示,从这里入手了解一下


还是从网页分析入手


image.png

一个简单的get请求,这是个静态网页,基本除了翻页以外,没有ajax请求,而对于翻页,我们可以直接构造url的方式来请求,经过测试,发现翻页的参数只是增加了一个page参数,那很简单 翻页循环我们已经可以写出来了,而且在利用postman 测试过后,发现爬虫请求连headers都不需要,对新手还是极其友好的.

列表页请求方法

image.png

有了翻页列表以后 ,我们就可以采集数据了,我们要采集的字段如下:

  1. 标题
  2. 作者
  3. 时间
  4. 文章链接
  5. 作者链接
image.png

然后我们就可以愉快的把数据爬下来了,但是仔细观察一下,发现这个发帖时间上 有点和我们预想的不一样


image.png

我们来看看网页怎么写的:


image.png
可以很清晰的看到,"相对时间"比"绝对时间"多了一个<span>,而且在相对时间的<span>里有个title属性,描述了"绝对时间",这样就不需要我们自己写脚本换算了,直接利用xpath取title的值即可

需要用到的包

from lxml import etree
import random
import time
import requests
import pymysql

信息提取方法:

image.png

时间替换方法:

image.png

是不是以为我要写好长的代码来实现这个方法?
一行就搞定了哦! 自己理解,不懂的话可以评论留言.

数据库初始化以及信息存储方法:

image.png
image.png
使用前建议先准备好相关的数据库环境以及创建数据表:
CREATE TABLE `fishc`  (
  `id` int(255) NOT NULL AUTO_INCREMENT,
  `标题` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `作者` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `发表时间` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `文章链接` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  `作者链接` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 ;

SET FOREIGN_KEY_CHECKS = 1;

这样一只爬虫就完成了

image.png
什么?这就爬完了?这就完事了?
不存在的,既然标题写了要分析数据 自然要点题啊
先上图:
2222.gif 111.gif

这图是怎么来的呢? 当然是从我们爬到的数据分析得来,


image.png

简单的统计了一下,排列出了在[作品展示]分类中,我们的[Charles未晞]和[jerryxjr1220]吊打全场作者有吗?

读取数据库中数据方法:

image.png

柱状图方法:

image.png

饼状图方法:

image.png

第一代饼状图:

QQ图片20180930174515.gif
密恐福利有么有?
其实笔者本人也是在不断的学习和练习各种插件,比如一开始的柱状图,x轴名称没有完全显示,而是隔一个条显示一个名字,就很纠结,后来通过百度(花了很久时间),也算是解决了这个问题(方法在图上代码中).
最后,让我们再次感谢[Charles未晞]和[jerryxjr1220]对鱼C论坛做的卓越贡献,辛苦了!
其实还可以生成词云图片的,这个我就不折腾了,之前的文章有词云可视化,就看你们的了!
附源码(数据采集):
#!/usr/bin/env python
""" 
@version: v1.0 
@author: 右哼哼
@contact: 1003582810@qq.com 
@site: https://fishc.com.cn
@software: PyCharm 
@file: 作品展示.py
@time: 2018/9/28 6:37 
"""
from lxml import etree
import random
import time
import requests
import pymysql


class FishC():
    def __init__(self):
        self.url = 'https://fishc.com.cn/forum.php'
        # 数据库初始化
        self.conn = pymysql.connect(
            host='localhost',
            port=3306,
            user='root',
            passwd='admin@123',
            db='test',
            charset='utf8'
        )
        # 创建游标
        self.cursor = self.conn.cursor()


    def get_html(self, page=1):
        data = {
            'mod': 'forumdisplay',
            'fid': 173,
            'filter': 'author',
            'orderby': 'dateline',
            'typeid': 729,
            'page': page,
        }
        html = requests.get(self.url, params=data).text
        return html

    def get_info(self,html):
        info = etree.HTML(html)
        title = info.xpath("//table/tbody/tr/th/a[2]/text()")
        author = info.xpath("//table[@id='threadlisttableid']/tbody[position()>1]/tr/td[2]//a/text()")
        # 取相对时间中的绝对时间
        time1 = info.xpath("//table[@id='threadlisttableid']/tbody[position()>1]/tr/td[2]//span/@title")
        # 取绝对时间
        time2 = info.xpath("//table[@id='threadlisttableid']/tbody[position()>1]/tr/td[2]//span/text()")
        links = info.xpath("//table/tbody/tr/th/a[2]/@href")
        aulinks = info.xpath("//table[@id='threadlisttableid']/tbody[position()>1]/tr/td[2]//a/@href")
        # 时间处理方法,替换'昨天,前天,3天前'等日期
        ctime = self.clear_info(time1,time2)
        return [title,author,ctime,links,aulinks]

    def clear_info(self,time1,time2):
        '''时间处理'''
        temp=time1+time2[len(time1):]
        return temp

    def save_tosql(self, data):
        '''写入Mysql数据库'''
        sql = "insert into fishc (标题,作者,发表时间,文章链接,作者链接) " \
              "VALUES ('%s','%s','%s','%s','%s')" \
              % (data[0], data[1], data[2], data[3],data[4])
        try:
            # 执行SQL
            self.cursor.execute(sql)
            self.conn.commit()

        except UnicodeEncodeError as e:
            print(e)  # 打印错误原因
            self.conn.rollback()  # 回滚数据库
            self.conn.close()  # 关闭数据库连接



if __name__ == '__main__':
    fc = FishC()
    for page in range(1,18):
        # 随机休眠,做一只理智的爬虫
        time.sleep(random.randint(1,4))
        print('第%d页'.center(20,'*') % page)
        #
        html = fc.get_html(page)
        info = fc.get_info(html)
        info_list = []
        for tit, aut, tim , link, aul in zip(info[0], info[1], info[2], info[3], info[4]):
            temp = [tit,aut,tim,link,aul]
            info_list.append(temp)
            fc.save_tosql(temp)

附源码(数据分析):

#!/usr/bin/env python   
""" 
@version: v1.0 
@author: Mr.Q   
@contact: 1003582810@qq.com 
@site:  
@software: PyCharm 
@file: 数据分析.py 
@time: 2018/9/30 7:57 
"""
import pymysql
import pyecharts
class Draw():
    def __init__(self):
        # 数据库连接初始化
        self.conn = pymysql.connect(
            host='localhost',
            port=3306,
            user='root',
            passwd='admin@123',
            db='test',
            charset='utf8'
        )
        # 创建游标
        self.cursor = self.conn.cursor()

    def read_data(self):
        sql = "select 作者, count(*) AS count from fishc  group by 作者 order by count DESC; "
        self.cursor.execute(sql)
        res = self.cursor.fetchall()
        return res

    def draw_bar(self,data):
        author, count = [], []
        for i in data:
            author.append(i[0])
            count.append(i[1])
        bar = pyecharts.Bar('作品展示分析',width=1000)
        bar.add('作品数量',author,count,is_more_utils=True,is_label_show=True,interval=0)
        bar.render('bar.html')

    def draw_pie(self,data):
        less , normal, large =[], [], []
        for i in data:
            if i[1] <=3:
                less.append(i[0])
            elif i[1] <=10:
                normal.append(i[0])
            elif i[1] >10:
                large.append(i[0])
            else:
                print(i)

        author, count = ['1~3篇','4~10篇','10+篇'], [len(less),len(normal),len(large)]
        pie = pyecharts.Pie('作品展示分布')
        pie.add('', author, count, is_label_show=True)
        pie.render('pie.html')

if __name__ == '__main__':
    dr = Draw()
    data = dr.read_data()
    dr.draw_bar(data[:10])
    dr.draw_pie(data)
上一篇 下一篇

猜你喜欢

热点阅读