亲爱的朋友们,我已经好久没有更新文章了
我一直以为自己在学习新的东西,学习更加深奥的东西 却没有注重积累 有点眼高手低了
这几天忙着做期末作业 需要用到python 自己写了个爬虫
不太擅长,但是最后自我感觉良好
介绍一下我用的编辑器 VS code 微软主推的跨平台编辑器
使用了很久(感觉啥文件都能兼容)问题总是有的,譬如插件拓展、无法识别文件
源码地址https://github.com/liyu19981212/python-
也可以复制下面的
用到了requests BeautifulSoup、re、pandas库
requests库用来请求网页数据
BeautifulSoup用来进行网页解析
re为正则表达式,因为从网页获取的文本可能会有格式问题
pandas是用来存储数据的
我爬取的网站是驾考宝典(后天我要考科目四了)
学会对url进行分析,每一个界面是如何变化的
第一页
第二页
写个循环就可以把所有的页面遍历了
jinan改成其他地面就是另一套数据了,自行发挥
里面涉及到库的使用都很简单
百度教程很多,希望深入一下,毕竟拿来主义还是不靠谱的
给大家贴一下我的源码
# -*- coding: utf-8 -*-
import requests
import re
from bs4 import BeautifulSoup
import pandas as pd
#代码框架
def getText(url,d,pages):
try:
name = []
address = []
price = []
score = []
stu_num = []
for k,v in d.items():
for p in range(1,pages+1):
new_url = url+k+'/school'+'/'+str(p)+'f.html'
headers = {'User-Agent':'Mozilla/5.0 Chrome/46.0.2490.80 '}
print(new_url)
r = requests.get(new_url,headers=headers, timeout=30)
r.raise_for_status #如果状态不是200,引发HTTPERROR异常
r.encoding = "utf-8"
# return r.text
soup = BeautifulSoup(r.text,'lxml')
#print(soup)
allinfo = soup.find('div',{'class','com-school-list com-part'})
allinfo = soup.find_all('li',{'class','clearfix'})
#print(allinfo)
#对每一个驾校的区块进行操作,获取驾校信息
for info in allinfo:
#驾校的名字
name1 = info.find_all('a',{'class':'title'})[0].get_text()
name1 = name1.replace('\n','').replace(' ','')
name.append(name1)
print(name1)
#驾校的地址
address1 = info.find_all('p',{'class':'field'})[0].get_text()
address1 = address1.replace('\n','').replace(' ','')
address.append(address1)
print(address1)
#学员数量
stu_num1 = info.find_all('span',{'class':'student'})[0].get_text()
stu_num1 = stu_num1.replace('\n','').replace(' ','')
stu_num.append(stu_num1)
print(stu_num1)
#驾校的价格
price1 = info.find_all('span',{'class':'price'})[0].get_text()
price1 == price1.replace('\n','').replace(' ','')
price.append(price1)
print(price1)
#驾校的评分
score1 = info.find_all('span',{'class':'score'})[0].get_text()
score1 == score1.replace('\n','').replace(' ','')
score.append(score1)
print(score1)
return name,address,price,score,stu_num
except Exception as e:
print(e)
#存储数据
def save_data(name,address,price,score,stu_num):
result = pd.DataFrame()
#result['v'] = v
result['name'] = name
result['address'] = address
result['price'] = price
result['score'] = score
result['stu_num'] = stu_num
result.to_csv('result.csv',encoding='utf-8_sig')
#主任务
def run():
first_url = "http://www.jiakaobaodian.com/"
d = {'jinan':'济南市'}
name,address,price,score,stu_num=getText(first_url,d,4)
save_data(name,address,price,score,stu_num)
#执行
if __name__ == '__main__':
run()
#fillUnivList(html)
内容不多,希望大家多多支持
现在是北京时间2019年12月24日
之前做完了后面的数据可视化和聚类分析但是没有时间上传
在不弄以后就没了
给大家分享一下后面的部分
# -*- coding: utf-8 -*-
import requests
import re
from bs4 import BeautifulSoup
import pandas as pd
from sklearn.cluster import KMeans #导入K均值聚类算法
import matplotlib.pyplot as plt
#从网页获取数据
def getText(url,d,pages):
#传入的三个参数分别为初始网页、数据字典、页码
try:
area = []
#驾校名称
name = []
#驾校地址
address = []
#价格
price = []
#评分
score = []
#学员数量
stu_num = []
#循环遍历
for k,v in d.items():
for p in range(1,pages+1):
#获取新的url
new_url = url+'jinan/school/'+k+'/'+str(p)+'f.html'
#模拟浏览器
headers = {'User-Agent':'Mozilla/5.0 Chrome/46.0.2490.80 '}
print(new_url)
#使用requests库
r = requests.get(new_url,headers=headers, timeout=30)
#状态码200
r.raise_for_status #如果状态不是200,引发HTTPERROR异常
#设置编码格式
r.encoding = "utf-8"
# return r.text
soup = BeautifulSoup(r.text,'lxml') #使用lxml解析
#print(soup)
#在这里用到的是beautifulsoup库
#定位到列表
allinfo = soup.find('div',{'class','com-school-list com-part'})
allinfo = soup.find_all('li',{'class','clearfix'})
#print(allinfo)
#对每一个驾校的区块进行操作,获取驾校信息
#遍历标签li
for info in allinfo:
#驾校的名字
name1 = info.find_all('a',{'class':'title'})[0].get_text()
#这里使用get_text()方法获取文本 去除文本中的标签元素
name1 = name1.replace('\n','').replace(' ','')
#正则表达式规范化格式
#将获取的数据放入name
name.append(name1)
print(name1)
#驾校的地址
address1 = info.find_all('p',{'class':'field'})[0].get_text()
address1 = address1.replace('\n','').replace(' ','')
address.append(address1)
print(address1)
#学员数量
stu_num1 = info.find_all('span',{'class':'student'})[0].get_text()
stu_num1 = stu_num1.replace('\n','').replace(' ','').replace('名学员','')
stu_num.append(stu_num1)
print(stu_num1)
#驾校的价格
price1 = info.find_all('span',{'class':'price'})[0].get_text()
price1 = price1.replace('¥','').replace(' ','').replace('面议','')
price.append(price1)
print(price1)
#驾校的评分
score1 = info.find_all('span',{'class':'score'})[0].get_text()
score1 = score1.replace('\n','').replace(' ','').replace('分','')
score.append(score1)
print(score1)
area.append(v)
return area,name,address,price,score,stu_num
except Exception as e:
print(e)
#存储数据
def save_data(area,name,address,price,score,stu_num):
#pandas中的DataFrame
result = pd.DataFrame()
#result['v'] = v
result['area'] = area
result['name'] = name
result['address'] = address
result['price'] = price
result['score'] = score
result['stu_num'] = stu_num
result.to_csv('result.csv',encoding='utf-8_sig') #此处的编码格式设置为utf-8_sig
#数据处理
def clean():
datafile= './result.csv'
#原始数据,第一行为属性标签
cleanedfile = './data_cleaned.csv'
#数据清洗后保存的文件
data = pd.read_csv(datafile,encoding='utf-8')
#读取原始数据,指定UTF-8编码
data = data[data['price'].notnull()&data['score'].notnull()]
#非空值才保留
#只保留非零的
index1 = data['price'] != 0
index2 = data['score'] != 0
index3 = data['stu_num'] != 0
data = data[index1 | index2 | index3] #该规则是“或”
data.to_csv(cleanedfile,encoding='utf-8_sig')
#导出结果
#可视化
def plot():
data = pd.read_csv('data_cleaned.csv',encoding='utf-8_sig')
d = data['area']
area = data['area'].drop_duplicates()
avgp = []
avgs = []
avgn = []
for a in area:
data1 = data[data['area']==a]
#平均价格取两位小数
avgp1 = round(float(data1['price'].mean()),2)
avgp.append(avgp1)
#平均评分
avgs1 = round(float(data1['score'].mean()),2)
avgs.append(avgs1)
#平均人数
avgn1 = data1['stu_num'].mean()
avgn.append(avgn1)
#print(a,avgp1,avgs1,avgn1)
#求各个区平均分
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.bar(area,avgs,color='SkyBlue')
plt.title('济南市各个区驾校平均评分(满分5分)')
plt.grid(True)
#plt.legend(lqu)
plt.xlabel('区名')
plt.ylabel('评分')
plt.show()
#求各个区平均价格
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.bar(area,avgp,color='SkyBlue')
plt.title('济南市各个区驾校平均价格')
plt.grid(True)
#plt.legend(lqu)
plt.xlabel('区名')
plt.ylabel('元')
plt.show()
#求各个区平均学员数量
plt.rcParams['font.family'] = ['sans-serif']
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.bar(area,avgn,color='SkyBlue')
plt.title('济南市各个区驾校平均学员数量')
plt.grid(True)
#plt.legend(lqu)
plt.xlabel('区名')
plt.ylabel('人')
plt.show()
#K-means聚类分析
def Kmeans():
inputfile = './data_cleaned.csv'
#待聚类的数据文件
outputfile = './fenlei.xlsx'
k = 3
#需要进行的聚类类别数
# iteration = 500
#聚类最大循环数
#读取数据并进行聚类分析
data = pd.read_csv(inputfile)
#读取数据
data = data[['price','score','stu_num']]
#调用k-means算法,进行聚类分析
kmodel = KMeans(n_clusters = k, n_jobs = 4)
#n_jobs是并行数,一般等于CPU数较好
kmodel.fit(data)
#训练模型
r1 = pd.Series(kmodel.labels_).value_counts()
#统计各个类别的数目
r2 = pd.DataFrame(kmodel.cluster_centers_)
#找出聚类中心
r = pd.concat([r2, r1], axis = 1)
#横向连接(0是纵向),得到聚类中心对应的类别下的数目
r.columns = list(data.columns) + [u'类别数目']
#重命名表头
print("聚类表结果:")
print (r)
r = pd.concat([data, pd.Series(kmodel.labels_, index = data.index)], axis = 1)
#详细输出每个样本对应的类别
r.columns = list(data.columns) + [u'聚类类别']
#重命名表头
r.to_excel(outputfile)
#保存分类结果
print("聚类图结果:")
p = data.plot(kind='kde', linewidth = 2, subplots = True, sharex = False)
[p[i].set_ylabel('density') for i in range(k)]
plt.legend()
# pic_output = 'D://mypy/' #概率密度图文件名前缀
#for i in range(k):
# density_plot(data[r[u'聚类类别']==i]).savefig(u'%s%s.png' %(pic_output, i))
#主任务
def run():
#url
first_url = "http://www.jiakaobaodian.com/"
#d可自由设定 需要理解key和value
d = {'q_lixia':'历下区','q_shizhong':'市中区','q_huaiyin':'槐荫区','q_tianqiao':'天桥区','q_licheng0':'历城区','q_changqing0':'长清区','q_pingyin':'平阴县','q_jiyang0':'济阳县','q_shanghe':'商河县','q_zhangqiu':'章丘市'}
#调用def
#获取数据
area,name,address,price,score,stu_num=getText(first_url,d,4)
#存储数据
save_data(area,name,address,price,score,stu_num)
#数据清洗
clean()
#绘图
plot()
#聚类分析
Kmeans()
#执行
if __name__ == '__main__':
run()
#fillUnivList(html)
运行结果如下:
希望有用
有缘关注一下