文章目錄
- 一、小說資料的獲取
- 二、資料的分析與可視化
- 2.1、Python讀取資料表時,有時候會發生一個很頑固的錯誤
- 2.2、查看表的統計資訊
- 2.3可視化圖分析
作者有話說:
1、本文雖然是一篇技術性文章,但是分析的資料可以給喜歡看小說的人提供參考
2、本文涉及的是Python爬蟲精進的知識
3、作者想通過分享,讓許多正在學習Python爬蟲的提供幫助,
4、如果你對代碼很反感,那就直接看資料分析吧!
5、文章若有不足之處,請指教,可以在評論區自由發表觀點以及提出問題,作者會及時回應,
一、小說資料的獲取
獲取的資料為起點中文網的小說推薦周榜的所有小說資訊,
網址為:https://www.qidian.com/rank/recom
源代碼對所有想要獲取的資料都有注釋,
# -*- coding: utf-8 -*-
"""
Created on Mon Jan 4 22:59:11 2021
"""
import requests
from bs4 import BeautifulSoup
import os.path
import csv
import time
import pymysql
import random
class DrawBookMessage():
def __init__(self):
"""
定義建構式,初始化最初網址,方便后面呼叫,不必重復寫
"""
self.baseUrl='https://www.qidian.com/rank/recom';
#定義baseurl目標網址
def User_Agent(self):
"""
定義5個代理IP隱藏身份,用5個IP隨機選取,以防止被檢測到鏈接物件而終止訪問
"""
user_agent1 = 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0'
user_agent2 = 'Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Safari/535.19'
user_agent3 ='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
#user_agent4 ='Mozilla/5.0 (Android; Mobile; rv:14.0) Gecko/14.0 Firefox/14.0'
#這個代理在我的開發環境中會發生訪問錯誤,作者注釋在這里,便于提醒自己
user_agent5 ='Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3'
lst = [user_agent1,user_agent2,user_agent3,user_agent5]
return random.choice(lst)#回傳隨機IP
def getHtml(self,url):
"""
通過隨機IP訪問網頁獲取網頁的內容
"""
user_agent = self.User_Agent()#獲取隨機IP
headers = {"User-Agent":user_agent}
request = requests.get(url,headers=headers).text#通過IP訪問網頁,并且獲取網頁內容請求
return request #回傳
def commonsdk(self,url):
"""
把文本型別轉換為<class 'bs4.BeautifulSoup'>型別,
之后還會用BeautifulSoup庫來提取資料,如果這不是一個BeautifulSoup物件,
我們是沒法呼叫相關的屬性和方法的,所以,這是非常重要,
"""
html = self.getHtml(url)
doc=BeautifulSoup(html,'lxml')#轉換為BeautifulSoup物件
return doc
def get_page_size(self,url):
'''獲取頁面總數'''
doc = self.commonsdk(url)
self.pageNum = doc.find("div",class_="pagination fr")['data-pagemax']
return int(self.pageNum)
def draw_base_list(self,url):
'''初級網頁內容'''
doc = self.commonsdk(url)
listt=doc.find('div',class_ = "book-img-text").find_all('div',class_ = 'book-mid-info')
for x in listt:
self.bookName = x.find('h4').text.strip()#書名
self.bookUrl ='https:'+x.find('h4').find('a')['href']#書的二級網址
self.bookAuthor = x.find('p').find(class_='name').text.strip()#
self.bookType = x.find('p').find('a',class_='').text.strip()#小說的型別
self.bookStatus = x.find('p').find('span').text.strip()#小說更新的狀態
self.draw_Second_list()#呼叫獲取二級網頁內容
self.dict_data()#呼叫生成字典的函式
def draw_Second_list(self):
'''獲取二級網頁內容'''
doc = self.commonsdk(self.bookUrl)
listt1 = doc.find('div',class_="book-info")
self.bookIntrodaction = listt1.find(class_="intro").text.strip()#獲取小說簡介
listt2 = doc.find(class_="fans-interact cf")
if listt2.find(class_ ='ticket rec-ticket')==None:#ticket rec-ticket為空,ticket rec-ticket hidde不為空,有月票的標簽
self. monthTickets = listt2.find(class_ ='ticket month-ticket').find(class_ = 'num').text#小說月票
self. weekTickets = listt2.find(class_ ='ticket rec-ticket hidden').find(class_ = 'num').text#小說周票
if listt2.find(class_ ='ticket rec-ticket hidden')==None:#ticket rec-ticket不為空,ticket rec-ticket hidde為空,沒有有月票的標簽
self. monthTickets=0#沒有月票標簽時,月票為0
self. weekTickets = listt2.find(class_ ='ticket rec-ticket').find(class_ = 'num').text #小說周票
self.weekWardNum = listt2.find(class_= 'rewardNum').text#小說本周打賞人數
def dict_data(self):
"""
定義一個人方法生成需要存入資料的字典
"""
ctime = time.strftime('%Y-%m-%d %H:%M:%S',time.localtime());#當前爬取時間
data={
'書名':self.bookName,
'作者':self.bookAuthor,
'型別':self.bookType,
'狀態':self.bookStatus,
'月票':int(self. monthTickets),
'周票':int(self.weekTickets),
'本周打賞人數':int(self.weekWardNum),
'本書簡介':self.bookIntrodaction,
'爬取時間':ctime
}
print(data)
print("="*50)
self.write_to_MySQL(data,"spiders","bookMessage")#寫入資料庫
self.write_to_scv(data,'bookMessage.csv')#寫入.CVS檔案
pass
def write_to_scv(self,dic,filename):
"""寫入csv檔案"""
file_exists = os.path.isfile(filename)#判斷是否為檔案
with open(filename, 'a',encoding='gb18030',newline='') as f: #a表示追加模式不覆寫原檔案中的內容,newline = "" 表示讀取的換行符保持不變,原來是啥,讀出來還是啥
headers=dic.keys()
w =csv.DictWriter(f,delimiter=',',lineterminator='\n',fieldnames=headers)#創建一個物件
if not file_exists :
w.writeheader()
w.writerow(dic)#單行寫入
print('當前行寫入csv成功!')
pass
def write_to_MySQL(self,dic,database,table_name):
""" 寫入資料庫"""
keys = ', '.join(dic.keys())
values = ', '.join(['% s'] * len(dic))#動態的構造占位符
db = pymysql.connect(host='localhost', user='root', password=(自己的資料庫密碼), port=3306, db=database)#連接資料庫
cursor = db.cursor()#資料庫連接物件
sql = 'INSERT INTO {table}({keys}) VALUES ({values})'.format(table=table_name, keys=keys, values=values)#插入陳述句
try:
if cursor.execute(sql, tuple(dic.values())):
print('Successful')
db.commit()#commit是把查詢陳述句提交到資料庫內
except:
print('Failed')
db.rollback()
cursor.close()#關閉物件
db.close()#關閉資料庫釋放資源
if __name__ == '__main__':
"""主函式"""
drawBook = DrawBookMessage()
page = drawBook.get_page_size(drawBook.baseUrl)
for x in range(1,page+1):
drawBook.draw_base_list(drawBook.baseUrl+'?page='+str(x))
看到這里不知道是否對你有所幫助?看不懂的可以評論區留言,順便點個贊,嘻嘻嘻嘻嘻嘻!
二、資料的分析與可視化
相信大家對pandas都有了解吧,我就直入主題——資料分析,
2.1、Python讀取資料表時,有時候會發生一個很頑固的錯誤

在這里一般性如果表中有中文的話,讀表的時候就會報這個錯誤,這里把默認編碼改為gbk一般就能解決這個問題,即encoding=‘gbk’,
2.2、查看表的統計資訊
(1)describe()查看表的相關資訊資訊
data.describe()
# count:數量統計,此列共有多少有效值
#std:標準差
#min:最小值
#25%:四分之一分位數
#50%:二分之一分位數
#75%:四分之三分位數
#max:最大值
#mean:均值

通過這個結果可以得出各票數的情況和打賞的人數,
(2)根據周票數對小說排序
我們通過排序可以篩選出周票數前5的小說
data.sort_values(by = '周票',ascending = False).head(5)

可以知道當前這5本小說人氣很高,很多人還喜歡看完結的小說,畢竟一次性看完的感覺特別爽,我們也把幾本完結的小說獲取出來
data.loc[data['狀態']=='完本'].sort_values(by = '周票',ascending = False)

可以得出最近100流行小說中只有2本是完結的,
2.3可視化圖分析
(1)折線圖
對于讀者,都有不同的喜好都市、有的喜好玄幻、有的喜歡輕小說……讓我們看一下最近這些小說各票數綜合情況,通過下面打代碼可以得出折線圖情況,
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
plt.rcParams['font.sans-serif'] = ['SimHei'] #解決橫坐標不能顯示中文的況
plt.rcParams['axes.unicode_minus'] = False#解決橫坐標不能顯示中文的情況
#三條縱坐標的值
y1 = data.groupby('型別').sum()['本周打賞人數']#求和
y2 = data.groupby('型別').mean()['周票']#求平均值
y3 = data.groupby('型別').mean()['月票']#求平均值
x=list(dict(y1).keys())#橫坐標值
fig = plt.figure(figsize=(8,6), dpi=100)#指定畫布大小
plt.plot(x,y1,c='red',label='打賞票和')指定折線的顏色和標簽
plt.plot(x,y2,c='green',label='周票均值')
plt.plot(x,y3,c='blue',label='月票均值')
plt.legend(loc='upper left')#標簽靠左
plt.ylabel('周票平局值、月票平局值、打賞票和',fontsize=15)改變定橫坐標名稱以及字體大小,
plt.title("小說票數折線圖")#圖名
plt.xlabel('小說型別',fontsize=15)
plt.show()

通過折線圖可以直觀的看書流行的趨勢,可以分析到奇幻小說最受歡迎,讀者最多,
(2)柱狀圖
在這里插入代碼片plt.rcParams['figure.figsize']=(8,3)#圖形大小
data.groupby(['型別']).mean().plot(kind = 'bar')
plt.xticks(rotation=0)#橫坐標的角度
plt.ylabel('number of people',fontsize = 15)#縱坐標名
plt.xlabel('Date',fontsize = 15)#橫坐標名

柱狀圖可以出月票、周票、以及打賞人數沒有很直接的關系,比如奇幻周票高,但是其他兩項的票數卻非常低,
(3)餅狀圖
sizes = []
for booktype in x:#x是上文折線圖中橫坐標,即小說所有的型別,
bookTypeNum=len(data[data['型別']==booktype])#獲取各種小說的數量
sizes.append(bookTypeNum)
plt.figure(figsize=(10,15)) #調節圖形大小
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
plt.pie(
sizes,
labels=x,#指定顯示的標簽
autopct='%1.1f%%'#資料保留固定小數位
)
#plt.axis('equal')# x,y軸刻度設定一致#本文中可以不用
plt.title('小說型別受歡迎的分布圖比')
plt.legend(loc='upper left')# 左上角顯示
plt.show()

通過餅狀圖可以得出奇幻、都市、仙俠、輕小說幾類小說很受大家追捧,
(4)詞云圖
import jieba
import wordcloud
string = ''
for i in range(len(x)):
string = str + (x[i])*int(sizes[i])
print(string)string=' '.join(string)
w = wordcloud.WordCloud(background_color='white',font_path='simfang.ttf')
#這里指明font_path時的字體一定要是自己電腦C:\windows\Fonts下包含有的字體,不然會報錯,或者出現亂碼,
w.generate(string)
w.to_file(r"bookMessage.png")

根據詞云的字的大小可以看出當下最受大家追捧的小說的型別,
(5)散點圖
import matplotlib.pyplot as plt
import numpy as np
plt.rcParams['figure.figsize']=(12,8)
np.random.seed(0) #執行多次每次獲取的亂數都是一樣的
colors = np.random.rand(100)
size = np.random.rand(20)*1000#隨機大小
plt.scatter(a,b,c=colors,s=size,alpha=0.7,marker='*')
plt.xlabel('月票數',fontsize = 15)#橫坐標名
plt.ylabel('周票數',fontsize = 15)#縱坐標名
plt.title("月票和周票散點圖")
plt.show()

通過散點圖可以得出大部分小說的月票和周票的數目很少,只有少數的小說月票和周票數目多,往往這些小說就是當下最火的小說,
結語:
本文到此結束,不知道螢屏前的你,有識訓了嗎?
你看過那些很火的小說呢?
你有哪些知識點看不懂或者需要幫助?
或者你只是路過,但相遇即是緣,不妨留下你的足跡哦!
歡迎留言點贊與我一起討論,我在世界的另一端等你哦!讓我們一起共同進步,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/246182.html
標籤:python
下一篇:Anaconda3+python3.7.0+pytorch1.6.0+cuda10.0+cudnn7.6.4+tensorflow1.15

