一、主题式网络爬虫设计方案
1.主题式网络爬虫名称:爬取豆瓣读书top250
2.主题式网络爬虫爬取的内容:书名,价格,出版时间,作者,翻译者,评论人数,评分
3.主题式网络爬虫设计方案概述:
思路:分析网页源代码,找出数据所在的标签,通过爬虫读取数据存入excel,对数据清洗分析
难点:爬取数据数量太多,所掌握的知识不够使用,爬取到的数据全都不是单纯的数字,所以在数据处理时遇到了许多问题
二、主题页面的结构特征分析
1.主题页面的结构与特征分析
爬取数据都分布在标签\'<div id="content">\'里,书名标签为\'div class="pl2"\',评分标签为\'span.class="rating_nums"等
2.Htmls页面解析
三、网络爬虫程序设计
1.数据爬取与采集
import requests from lxml import etree import csv import pandas as pd import matplotlib.pyplot as plt import seaborn as sns headers={ \'User-Agent\':\'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36\' \'(KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4209.400\' } def get_one_page(url): url = \'https://book.douban.com/top250?start=0\' response = requests.get(url,headers=headers) #将网页数据装换成Html对象 html = etree.HTML(response.text) book_name = html.xpath(\'//div[@class="pl2"]/a/@title\') #爬取书名 rating_nums = html.xpath(\'//span[@class="rating_nums"]/text()\') #爬取评价分数 raint_people_ = html.xpath(\'//span[@class="pl"]/text()\') #爬取评价人数 raint_people = [] for i in raint_people_: raint_people.append(i.strip(\'()\n 人评价\')) book_infos = html.xpath(\'//p[@class="pl"]/text()\')#爬取书籍信息 author = [] translator = [] publisher = [] time = [] price = [] for j in book_infos: data = j.split(\'/\') author.append(data[0]) translator.append(data[1] if len(data) == 5 else \' \') publisher.append(data[-3]) time.append(data[-2]) price.append(data[-1]) book_data = [] for i in range(25): book_data.append([book_name[i],author[i],translator[i],publisher[i],time[i],price[i],rating_nums[i],raint_people[i]]) print(book_data) return book_data #数据持久化 with open(\'豆瓣top250.csv\',mode=\'w\',newline=\'\',encoding=\'utf-8\') as f: writer = csv.writer(f) writer.writerow([\'书名\',\'作者\',\'翻译者\',\'出版社\',\'出版日期\',\'价格\',\'评分\',\'评价人数\']) for i in range(10): print(\'页数\'+str(i+1)) link = \'https://book.douban.com/top250?start=\' + str(i*25) for i in get_one_page(link): writer.writerow(i)
2.对数据进行清洗和处理
df = pd.DataFrame(pd.read_csv(\'豆瓣top250.csv\'))#数据进行清洗和处理 df.head()
df.duplicated()#检查是否有重复值
df.isnull().sum()#控制处理
df[df.isnull().values==True]#缺失值处理
df.describe()#用describe()命令显示描述性统计指标
3.数据分析与可视化
#绘制评价人数与评分柱状图 plt.rcParams[\'axes.unicode_minus\']=False #用来正常显示负号 plt.bar(df.评分, df.评价人数, label="评价人数与评分柱状图") plt.show() plt.rcParams[\'font.sans-serif\']=[\'STSong\']
#绘制评价人数与评分散点图 def Scatter_point(): plt.scatter(df.价格, df.评分, color=\'red\', s=25, marker="o") plt.xlabel("评价人数") plt.ylabel("评分") plt.title("评价人数与评分-散点图") plt.show() Scatter_point()
#绘制排名与评分-盒图 def draw1(): plt.figure(figsize=(10, 6)) plt.title(\'绘制评价人数与评分-盒图\') sns.boxplot(x=\'评价人数\',y=\'评分\', data=df) draw1()
#绘制评价人数与评分的回归图 plt.rcParams[\'font.sans-serif\']=[\'STSong\']#显示中文 sns.regplot(df.评价人数,df.评分)
#绘制部分分布图 sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'re
#绘制排名与热度折线图 def draw(): x = df[\'评价人数\'] y = df[\'评分\'] plt.xlabel(\'评价人数\') plt.ylabel(\'评分\') plt.plot(x,y) plt.scatter(x,y) plt.title("绘制评价人数与评分折线图") plt.show() draw()
#绘制部分分布图 sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'kde\', color=\'r\') sns.jointplot(x="评价人数",y=\'评分\',data = df) sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'reg\') sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'hex\')
#绘制一元一次回归方程 import numpy as np from scipy.optimize import leastsq import pandas as pd def main(): colnames = ["价格", "评分"] df = pd.read_csv(\'豆瓣top250.csv\',skiprows=1,names=colnames) X = df.价格 Y = df.评分 def func(p, x): k, b = p return k * x + b def error_func(p, x, y): return func(p,x)-y p0 = [0,0] Para = leastsq(error_func, p0, args = (X, Y)) k, b = Para[0] print("k=",k,"b=",b) plt.figure(figsize=(10,6)) plt.scatter(X,Y,color="green",label=u"评分分布",linewidth=2) x=np.linspace(0,30,20) y=k*x+b plt.plot(x,y,color="red",label=u"回归方程直线",linewidth=2) plt.title("豆瓣top250") plt.xlabel(\'价格\') plt.ylabel(\'评分\') plt.legend() plt.show() main()
5.数据持久化
#数据持久化 with open(\'豆瓣top250.csv\',mode=\'w\',newline=\'\',encoding=\'utf-8\') as f: writer = csv.writer(f) writer.writerow([\'书名\',\'作者\',\'翻译者\',\'出版社\',\'出版日期\',\'价格\',\'评分\',\'评价人数\']) for i in range(10): print(\'页数\'+str(i+1)) link = \'https://book.douban.com/top250?start=\' + str(i*25) for i in get_one_page(link): writer.writerow(i)
6.将以上各部分的代码汇总,附上完整程序代码:
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 23 08:17:48 2020
@author: Administrator
"""
#数据爬取和采集
import requests
from lxml import etree
import csv
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
headers={
\'User-Agent\':\'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36\' \'(KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3775.400 QQBrowser/10.6.4209.400\'
}
def get_one_page(url):
url = \'https://book.douban.com/top250?start=0\'
response = requests.get(url,headers=headers)
#将网页数据装换成Html对象
html = etree.HTML(response.text)
book_name = html.xpath(\'//div[@class="pl2"]/a/@title\') #爬取书名
rating_nums = html.xpath(\'//span[@class="rating_nums"]/text()\') #爬取评价分数
raint_people_ = html.xpath(\'//span[@class="pl"]/text()\') #爬取评价人数
raint_people = []
for i in raint_people_:
raint_people.append(i.strip(\'()\n 人评价\'))
book_infos = html.xpath(\'//p[@class="pl"]/text()\')#爬取书籍信息
author = []
translator = []
publisher = []
time = []
price = []
for j in book_infos:
data = j.split(\'/\')
author.append(data[0])
translator.append(data[1] if len(data) == 5 else \' \')
publisher.append(data[-3])
time.append(data[-2])
price.append(data[-1])
book_data = []
for i in range(25):
book_data.append([book_name[i],author[i],translator[i],publisher[i],time[i],price[i],rating_nums[i],raint_people[i]])
print(book_data)
return book_data
#数据持久化
with open(\'豆瓣top250.csv\',mode=\'w\',newline=\'\',encoding=\'utf-8\') as f:
writer = csv.writer(f)
writer.writerow([\'书名\',\'作者\',\'翻译者\',\'出版社\',\'出版日期\',\'价格\',\'评分\',\'评价人数\'])
for i in range(10):
print(\'页数\'+str(i+1))
link = \'https://book.douban.com/top250?start=\' + str(i*25)
for i in get_one_page(link):
writer.writerow(i)
#读取CSV文件
df = pd.DataFrame(pd.read_csv(\'豆瓣top250.csv\'))#数据进行清洗和处理
df.head()
df.duplicated()#检查是否有重复值
df.isnull().sum()#控制处理
df[df.isnull().values==True]#缺失值处理
df.describe()#用describe()命令显示描述性统计指标
#数据可视化
#绘制评价人数与评分柱状图
plt.rcParams[\'axes.unicode_minus\']=False #用来正常显示负号
plt.bar(df.评分, df.评价人数, label="评价人数与评分柱状图")
plt.show()
plt.rcParams[\'font.sans-serif\']=[\'STSong\']
#绘制评价人数与评分散点图
def Scatter_point():
plt.scatter(df.价格, df.评分, color=\'red\', s=25, marker="o")
plt.xlabel("评价人数")
plt.ylabel("评分")
plt.title("评价人数与评分-散点图")
plt.show()
Scatter_point()
#绘制排名与评分-盒图
def draw1():
plt.figure(figsize=(10, 6))
plt.title(\'绘制评价人数与评分-盒图\')
sns.boxplot(x=\'评价人数\',y=\'评分\', data=df)
draw1()
#绘制评价人数与评分的回归图
plt.rcParams[\'font.sans-serif\']=[\'STSong\']#显示中文
sns.regplot(df.评价人数,df.评分)
#绘制部分分布图
sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'reg\')
#绘制排名与热度折线图
def draw():
x = df[\'评价人数\']
y = df[\'评分\']
plt.xlabel(\'评价人数\')
plt.ylabel(\'评分\')
plt.plot(x,y)
plt.scatter(x,y)
plt.title("绘制评价人数与评分折线图")
plt.show()
draw()
#绘制部分分布图
sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'kde\', color=\'r\')
sns.jointplot(x="评价人数",y=\'评分\',data = df)
sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'reg\')
sns.jointplot(x="评价人数",y=\'评分\',data = df, kind=\'hex\')
四、结论
1.结论:经过对主题数据的分析与可视化,突出了各数据间的关系和各数据呈现出来的分布,通过数据分析和可视化让抽象的数据变成具体的图像,让我们的理解更加容易,解决了大部分人工计算绘图等繁杂过程,能够通过爬虫爬取信息并运用其他库处理信息对工作效率的提升是多么的大,提高了自己对python的兴趣,坚定了认真学习的目标。
2.小结:通过这次做题任务,我明白了数据的分析与可视化,掌握了不少库的使用,期间有在百度上等地方进行学习,此次任务有所收获,加深了对python的热爱通过这次做题任务,我在完成的过程中遇到了很多的困难,让我得到了许多收获,也让我充分的认识到了自己的不足之处,在未来我将更加努力的学习。