#sum 多页 入库成功 爬取文件中所有的店铺 网页完整表端 去除重复数据 遇到空页面会跳到下一家店铺 。遇到某家店铺无数据,跳过去下一家
#爬去某家店铺指定的页数(一页记录数默认大小为100条),比如爬取12页,则爬取12页后将结果一次性写入数据库
#爬去整个页面表结构,再分别写入4张表中(爬取的数据存入两张表中,还有超标表 异常表)
#网页上字段共14个,存入数据库是15个(序号+14)
import requests
from bs4 import BeautifulSoup as bs
import re #正则表达式
from pymysql import * # 连接mysql数据库
import pandas as pd
from sqlalchemy import create_engine
import urllib.parse #url双重编码
import time
import uuid
from datetime import datetime, timedelta
import sys
# sys.path.append('D:\\z\workplace\\VsCode\\pyvenv\\venv')
sys.path.append('../../')
# import core_modules.remove_duplicates_methods as rdm
import src.core_modules.remove_duplicates_methods as rdm
now_date = time.strftime("%Y-%m-%d", time.localtime()) #获取当前年月日 #url编码年月日开始默认时间
now_date1 = time.strftime("%Y-%m", time.localtime())
month_begin=now_date1+'-01' #设置当前月份的开始
list_temp=[] #临时列表 全局变量
def remove_Duplicates_list(list): #列表自身去重
global already_spider_datanum
list_store=[]
for item in list:
if item not in list_store:
list_store.append(item)
else:
print("发现重复")
already_spider_datanum=already_spider_datanum-1
#print(list_store)
return list_store
def merge(list): #合并list倒数六个元素
date_1=str(list.pop(-1)) #删除尾元素后还能继续使用改元素,
date_2=str(list.pop(-1))
date1=date_2+' '+date_1 #合并为年月日时分秒
date_3=str(list.pop(-1))
date_4=str(list.pop(-1))
date2=date_4+' '+date_3
date_5=str(list.pop(-1))
date_6=str(list.pop(-1))
date3=date_6+' '+date_5
list.append(date3) #将合并的数据写会list列表结尾.
list.append(date2)
list.append(date1)
return list
def list_url(url,page_num): #url中的i是页 ,apge_num表示爬取的页数 。url后面加上页的参数
urls = [url+'&page'+'={}'.format(str(i)) for i in range(1,page_num+1)]
return urls # 返回该url对应页的所有链接形式,返回值为列表
def get_OnePage(url,count): #抓取一页的数据,放入list_data中.urls为要访问的网页地址
# global ck
global list_temp #使用全局变量
list_temp.clear() #清空临时表
# session.headers = {
# # 此处注意cookie,要自己抓取
# # "Cookie":ck,
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
# }
r = session.get(url, verify=False).text
soup = bs(r,'html.parser')
list=[] #创建列表来保存结果
tags = soup.find_all("tr") # 列表所有行
for tag in tags: # 每个tag是一行
count=count+1
element = tag.text # 获取
标签内所有文本信息
element = element.strip() # 将字符串首尾空格去除
list1 = element.split(); # 以空格为分隔将字符串变为列表
del (list1[-2:]) #列表最后两个元素不需要,删除
list1.insert(3,'')
list.append(list1) #list保存所有行
#print(list)
list_data=[] #保存合并日期的一页数据
for i in list:
list_data.append(merge(i)) #已将尾日期数据合并成年月日 时分秒 此时形成完整的数据.
del list_data[0] #删除文字表头
count=count-1 #删除了表头,总数据的行数减一
#list_removeD= remove_Duplicates_list(list_data) #list_date保存的是一页的数据
#print(list_data)
list_temp=list_data[:]
#list_temp=remove_Duplicates_list(list_data)[:] #将一页所有数据复制给临时列表list_temp 是去除重复后的列表
return count
def get_MorePages(url,page_num): #爬取指定店铺名的多页数据,apge_num表示爬取的页数
global sleeptime
global already_spider_datanum
urls=list_url(url,page_num) #得到需要遍历的页的url
count_all=0 #保存数据的总行数
list_all=[] #保存爬取的所有的数据
page=1
for i in urls:
count=0
count_all=count_all+get_OnePage(i,count)
if len(list_temp)==0: #如果该页为空,则表示该页后面都无数据 退出循环
print('后面页数为空,爬去下一个店铺')
break #退出循环
list_all.extend(list_temp) #将一页数据列表追加到list_all中
print("爬取了第",page,"页")
page=page+1
print("\n")
time.sleep(sleeptime) #间隔2秒请求一次
for j in list_all:
print(j) #打印列表中每一行
print("总行数为:",count_all)
already_spider_datanum += count_all #已爬取数据的总和
return list_all
#return remove_Duplicates_list(list_all) #再次对列表过滤重复
def url_more(): #返回文件中铺名编码形成url,返回值是url列表 默认查看网页的最大显示条数100
global shopnum
global webshops
shopnames = webshops[:] #保存中文店铺名称
print('url_more:',shopnames)
# print('')
# with open("D:\\z\\workplace\\shopname.txt",encoding='utf-8') as file: #将文件中店铺名字保存到列表中
# for line in file:
# line = line.strip() #or some other preprocessing
# shopnames.append(line) #storing everything in memory!
#print(type(shopnames[0]))
#编码
shopnum=len(shopnames) #文件中店铺总数
shopname_encoding=[] #保存编码后的店铺名称
i=0
for name in shopnames:
shopname_encoding.append(urllib.parse.quote(urllib.parse.quote(shopnames[i]))) #店铺名称进行双重url编码
i=i+1
#拼接网址形成可用的url
urls=[] #保存拼接后的url
for shop in shopname_encoding:
url='http://xhhb.senzly.cn/sys/yyRealTimeValue_list.jsp?key1=&shop='+shop+'&pagesize=100'
urls.append(url)
# for i in urls:
# print(i)
return urls #返回文件中店铺名称对应的url
#根据开始和结束日期来拼接url
def url_add_time(url,date_begin=month_begin,date_end=now_date): #url,年-月-日 2023-05-03
url_date=url+'&key5='+date_begin+'&key6='+date_end
print(url_date)
return url_date
#------------------------------------------------------------------------------------------------------------超标油烟数据写入异常表中
#两时间是否相差10分钟 是则返回TRUE 否则返回FALSE
def is_time_difference_equals_10_mins(datestr1, datestr2):
date1 = datetime.strptime(datestr1, "%Y-%m-%d %H:%M")
date2 = datetime.strptime(datestr2, "%Y-%m-%d %H:%M")
time_diff = date2 - date1
return time_diff == timedelta(minutes = 10) or time_diff == timedelta(minutes = -10) #timedelta() 表示两个 date 对象或者 time 对象,或者 datetime 对象之间的时间间隔
#每隔十分钟一次为正常。 找出超过10分钟的间断点
def find_break_point(list): #list为超标数据的列表
i=0
j=1
break_point = [] #保存间断点
for item in list[1:]:
if(is_time_difference_equals_10_mins(list[i][2],item[2]) == False):
break_point.append(j)
i=i+1
j=j+1
print('间断点为:')
print(break_point)
#写入间断点
return break_point
#根据间断点将列表分割成几个子列表,由result返回
def point_write(list,b_point): #list为列表。b_point列表元素为间断点,间断点值从小到大
result = []
last_index = 0
for index in b_point:
result.append(list[last_index:index]) #灵活
last_index=index
result.append(list[last_index:])
return result
#将设备故障信息写入abnormal_data异常表中
def abnormal_write_to_SQL(list,con):
data = pd.DataFrame(list,columns=['dev_id','exception','exception_type','region','begin_time','end_time'])
print("\n\n")
print(data)
# engine = create_engine("mysql+mysqlconnector://root:1234@localhost:3306/fume?charset=utf8")
# con = engine.connect()
# test3 要写入的数据表,这样写的话要提前在数据库建好表
data.to_sql(name="abnormal_data", con=con, if_exists="append",index=False,index_label=False)
# con.close()
def exception(list,con): #list为超标数据的列表
break_point=find_break_point(list) #返回间断点
split_list=point_write(list,break_point) #根据间断点将原始列表分割成几个子列表 split_list为三层数组,形式为[[[1,2],[4,'g']],[[8,'2'],['4','g']],[[1,2],[4,'g']]]
# print('超标时间段划分成的子列表为::')
# for i in split_list:
# print(i)
print('\n')
abnormal=[] #重组好的异常表数据
for item in split_list: #从分割的数组中提取需要的时间信息,并添加新的信息数据
temp=[]
temp.append(item[0][0]) #设备编号
temp.append('数据异常') #设备编号
temp.append('0') #油烟浓度超标
temp.append('徐汇区')
temp.append(item[len(item)-1][2]) #前一条记录的归属时间 开始时间
temp.append(item[0][2]) #归属时间 结束时间
abnormal.append(temp)
print(abnormal)
print('超标异常时间段数据为:')
for j in abnormal:
print(j)
abnormal_write_to_SQL(abnormal,con) #写入异常表中
print("超标油烟数据异常表写入完成!")
#------------------------------------------------------------------------------------------------------------设备故障数据写入异常表中
#两时间是否相差30分钟 是则返回TRUE 否则返回FALSE
def is_time_difference_equals_30_mins(datestr1, datestr2):
date1 = datetime.strptime(datestr1, "%Y-%m-%d %H:%M")
date2 = datetime.strptime(datestr2, "%Y-%m-%d %H:%M")
time_diff = date2 - date1
return time_diff > timedelta(minutes=30)
#找出设备故障的信息,并将此信息写入异常表中
def is_minutes_exceed_30(list,con) : # list为某店铺指定页数的全部的记录 list元素中的时间为倒序排列,即从大到小
device_failure=[] #存储设备故障的数据
startTime = list[0][11]
print('开始时间:',startTime)
for item in list[1:] :
if is_time_difference_equals_30_mins(item[11],startTime) : #必须大于30分钟 不能等于30分钟
temp=[]
temp.append(item[2]) #设备编号
temp.append('设备故障') #设备编号
temp.append('1') #设备故障
temp.append('徐汇区')
temp.append(item[11]) #故障开始时间
startTimeSub= datetime.strptime(startTime,"%Y-%m-%d %H:%M") - timedelta(minutes = 10) #结果为datetime.datetime类型 ,需要再转为字符串类型
print('相减后结果:',str(startTimeSub))
print('相减后类型:',type(str(startTimeSub)))
temp.append(str(startTimeSub)[:16]) #故障结束时间
device_failure.append(temp)
startTime = item[11]
print('设备故障的数据为:')
for i in device_failure :
print(i)
not_Key_period_exceed_30_minutes(device_failure,con) #将供电异常信息写入异常表
#abnormal_write_to_SQL(device_failure,con) #将设备故障信息写入异常表
print('供电异常/掉线信息写入异常表完成!')
#-----------------------------------------------------------------------------------------------------------供电异常数据写入异常表中
#开始和结束时间都处于非重点时段时,返回true
def is_time_not_between_key_period(begin_time,end_time) : #形参为日期字符串,形如 '2023-06-21 14:30'
global Key_period_noon_begin,Key_period_noon_end,Key_period_night_begin,Key_period_night_end
# #中午重点时段
# Key_period_noon_begin = datetime.strptime('10:00',"%H:%M")
# Key_period_noon_end = datetime.strptime('14:00',"%H:%M")
# #晚上重点时段
# Key_period_night_begin = datetime.strptime('17:00',"%H:%M")
# Key_period_night_end = datetime.strptime('21:00',"%H:%M")
begin1 = datetime.strptime(begin_time[11:],"%H:%M")
end1 = datetime.strptime(end_time[11:],"%H:%M")
#当开始和结束时间都处于非重点时段时,将该条故障信息同时记录为: 疑似供电异常
if ((( begin1 > Key_period_noon_begin and begin1 < Key_period_noon_end ) or ( begin1 > Key_period_night_begin and begin1 < Key_period_night_end )) or (( end1 > Key_period_noon_begin and end1 < Key_period_noon_end ) or ( end1 > Key_period_night_begin and end1 < Key_period_night_end ))) ==False :
print('开始或结束时间时间在非重点时段')
return True
print('处于重点时段')
return False
#开始和结束时间都处于重点时段时,返回true
def is_time_between_key_period(begin_time,end_time) : #形参为日期字符串,形如 '2023-06-21 14:30'
global Key_period_noon_begin,Key_period_noon_end,Key_period_night_begin,Key_period_night_end
# #中午重点时段
# Key_period_noon_begin = datetime.strptime('10:00',"%H:%M")
# Key_period_noon_end = datetime.strptime('14:00',"%H:%M")
# #晚上重点时段
# Key_period_night_begin = datetime.strptime('17:00',"%H:%M")
# Key_period_night_end = datetime.strptime('21:00',"%H:%M")
begin1 = datetime.strptime(begin_time[11:],"%H:%M")
end1 = datetime.strptime(end_time[11:],"%H:%M")
#当开始和结束时间都处于重点时段时,将该条故障信息同时记录为: 掉线
if ((begin1 > Key_period_noon_begin and begin1 < Key_period_noon_end) and ( end1 > Key_period_noon_begin and end1 < Key_period_noon_end )) or ( (begin1 > Key_period_night_begin and begin1 < Key_period_night_end) and ( end1 > Key_period_night_begin and end1 < Key_period_night_end )) :
print('开始或结束时间处于重点时段')
return True
print('处于非重点时段')
return False
def not_Key_period_exceed_30_minutes(list,con) : #list为设备故障的时间段数据
power_supply_abnormal = [] #保存供电异常或掉线的信息
for item in list :
if is_time_not_between_key_period(item[4],item[5]) : #else:
temp = []
temp.append(item[0])
temp.append('设备故障')
temp.append('1') #疑似供电异常
temp.append('徐汇区')
temp.append(item[4])
temp.append(item[5])
power_supply_abnormal.append(temp)
elif is_time_between_key_period(item[4],item[5]) :
temp = []
temp.append(item[0])
temp.append('设备故障')
temp.append('2') #掉线
temp.append('徐汇区')
temp.append(item[4])
temp.append(item[5])
power_supply_abnormal.append(temp)
print('供电异常的数据为:')
for i in power_supply_abnormal :
print(i)
#将供电异常的信息写入数据库异常表中
abnormal_write_to_SQL(power_supply_abnormal,con) #将设备故障信息写入异常表
print('供电异常的信息写入异常表完成!')
#------------------------------------------------------------------------------------------------------------写入超标表中
#返回重组后的列表
def refind_ex(list): #list为网页的一条记录
temp=[]
temp.append(list[2]) #设备编号
temp.append(list[12]) #上报时间
temp.append(list[11]) #归属时间
temp.append(list[6]) #风机电流 6
temp.append(list[7]) #净化器电流7
temp.append(list[4]) #进油烟浓度值
temp.append(list[5]) #排油烟浓度值
print(temp)
return temp
#将列表写入exceeding_st_data表中
def ex_write_to_SQL(list,con):
data = pd.DataFrame(list,columns=['MV_Stat_Code','MV_Create_Time','MV_Data_Time','MV_Fan_Electricity','MV_Purifier_Electricity','MV_Fume_Concentration','MV_Fume_Concentration2'])
print("\n\n")
print(data)
#engine = create_engine("mysql+mysqlconnector://root:1234@localhost:3306/fume?charset=utf8")
#con = engine.connect()
# test3 要写入的数据表,这样写的话要提前在数据库建好表
data.to_sql(name="exceeding_st_data", con=con, if_exists="append",index=False,index_label=False)
#con.close()
print("超标表写入完成!")
# list为某店铺指定页数的全部的记录 将超标数据写入超标表
def isExceeding(list,con): #list为某店铺指定页数的全部的记录 list元素为列表形式
exceedingData=[] #保存超标的数据
for item in list: #查找超标的数据,并记录下
if float(item[5]) > 1: # 排烟浓度大于1则超标
print("该条数据超标")
#保存该条记录,提取需要的值,并添加其他字段
exceedingData.append(refind_ex(item))
for i in exceedingData: #遍历列表
print(i)
if(len(exceedingData) != 0) : #有超标数据时才执行
#将超标数据时间分类再写abnormal_data异常表中
exception(exceedingData,con)
#将超标数据直接写入数据库超标表中
ex_write_to_SQL(exceedingData,con)
else:
print('该店铺无超标数据')
#------------------------------------------------------------------------------------------------------------数据写入设备信息表
def generate_short_uuid():
arrayOf=[
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z"
]
list=[]
ui=str(uuid.uuid4()).replace('-', '')
for i in range(0,16):
a1=ui[i*2:i*2+2]
x=int(a1,16)
list.append(arrayOf[x % 0x3E])
return ''.join(list)
#返回重组后的列表
def refind_ea(list): #一条记录,也就是一个列表
temp=[]
temp.append(generate_short_uuid())
temp.append(list[2])
temp.append(list[1])
temp.append(list[0])
temp.append(1)
print(temp)
return temp
#将列表写入设备信息设备信息ea_t_dev表中
def ea_write_to_SQL(list,con):
data = pd.DataFrame(list,columns=['DI_GUID','DI_Code','DI_Name','DI_Supplier','DI_Online'])
print("\n\n")
print('写入数据表 ,DateFrame为:',data)
# test3 要写入的数据表,这样写的话要提前在数据库建好表
data.to_sql(name="ea_t_device_info", con=con, if_exists="append",index=False,index_label=False)
print("设备信息表写入完成!")
def dev_info_data_if_exisitd(list,con): #list为爬取某家店铺指定页数转换后的数据
global con_read
#创建第二个数据库连接
# engine = create_engine("mysql+mysqlconnector://root:1234@localhost:3306/fume?charset=utf8")
# con_read = engine.connect()
df = pd.read_sql('SELECT DI_Code,DI_Name,DI_Supplier FROM ea_t_device_info',con=con_read) #从设备信息表中读取设备编号,店铺名,供应商字段的数据。返回值是DateFrame类型
# con_read.close() #关闭链接
res = df.values.tolist() #DateFrame按照行转成list类型,res存放的是设备信息表中的数据
print('******** 设备信息******')
for i in res:
print(i)
print('设备信息表记录条数为:',len(res))
list1 = rdm.remove_duplicates_dev_info(list) #设备编号,店铺名,供应商相等时,则为重复,去除。list1为去重后的
if len(res) > 0 : #设备表中有数据
#比较
temp=list1[:] #将list1数据给temp,遍历temp,若相等,从list中删除数据,避免一个列表同时遍历且删除
print('去除重复为:')
print(list1)
for item in temp:
if item[1:4] in ( x[:] for x in res ) : #待存入数据库的值与设备表中数据相等时,将待存入的值从list中移除
list1=rdm.remove_given_data_dev_info(list1,item[1:4]) #该item从list1中移除
print('设备信息表中有数据时,去重后的list为:',list1)
if( len(list1) != 0 ) : #删除后不为空时,写入
ea_write_to_SQL(list1,con) #将列表写入ea_t_dev表中
else : #设备表中无数据
# a=rdm.remove_duplicates_dev_info(list) #设备编号,店铺名,供应商相等时,则为重复,去除
print('设备表无数据,处理后待写入的设备信息为:',list1)
#将去重后数据写入设备信息表
ea_write_to_SQL(list1,con) #将列表写入设备表中 。 第一个参数:设备编号,店铺名,供应商相等时,则为重复,去除
#将原始数据转化成新的列表,再写入设备信息设备信息表中 /存入
def ea_t_dev(list,con): #某家店铺的制定页的数据记录 ,list列表元素依然为列表,比如[[1,2,3,'a'],[52,3,'a'],[6,2,3,'a']] ,con为数据库的建立
staging=[] #表示转换后的列表
for item in list:
#提取需要的值,并添加其他字段
staging.append(refind_ea(item)) #转化
print('设备数据转化后:')
for i in staging:
print(i)
#查询设备表已存的数据,若已存在设备信息,则不写入
dev_info_data_if_exisitd(staging,con)
#----------------------------------写入分钟数据表
#返回重组后的列表
def refind_fd(list): #一条记录,也就是一个列表
temp=[]
temp.append(list[2]) #设备编号
temp.append(list[12]) #上报时间
temp.append(list[11]) #归属时间
temp.append(list[6]) #风机电流 6
temp.append(list[7]) #净化器电流 7
temp.append(list[4]) #进油烟浓度值
temp.append(list[5]) #排油烟浓度值
print(temp)
return temp
#将列表写入分钟数据表中
def fd_write_to_SQL(list,con):
data = pd.DataFrame(list,columns=['MV_Stat_Code','MV_Create_Time','MV_Data_Time','MV_Fan_Electricity','MV_Purifier_Electricity','MV_Fume_Concentration','MV_Fume_Concentration2'])
print("写入分数数据表,DateFrame为:")
print(data)
# test3 要写入的数据表,这样写的话要提前在数据库建好表
data.to_sql(name="fd_t_minutevalue", con=con, if_exists="append",index=False,index_label=False)
print("分钟数据表写入完成!")
#转化 再写入fd_t_minbute表中
def fd_t_minbute(list,con): #一页的数据记录 ,con为数据库的建立
staging=[] #保存转换后的列表
for item in list:
#提取需要的值,并添加其他字段
staging.append(refind_fd(item))
print('分钟数据转化后:')
for i in staging:
print(i)
fd_write_to_SQL(staging,con) #将列表写入ea_t_dec表中
#--------------------------------------------------------------------------------------------------------------食其家
def get_OnePage_teshu_shiqijia(url,count):
global ck
global list_temp #使用全局变量
list_temp.clear() #清空临时表
# session.headers = {
# # 此处注意cookie,要自己抓取
# # "Cookie":ck,
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
# }
r = session.get(url, verify=False).text
soup = bs(r,'html.parser')
list=[] #创建列表来保存结果
tags = soup.find_all("tr") # 列表所有行
for tag in tags: # 每个tag是一行
count=count+1
element = tag.text # 获取
标签内所有文本信息
element = element.strip() # 将字符串首尾空格去除
list1 = element.split(); # 以空格为分隔将字符串变为列表
del (list1[-2:]) #列表最后两个元素不需要,删除
print('删除特殊的后两个')
print(list1)
str_temp1=list1[4]+list1[5] #第5,6合并两个元素为一个
print(str_temp1)
del list1[5]
list1[4]=str_temp1
print("元素合并完成")
print(list1)
str_temp2=list1[1]+list1[2] #第二三元素合并完成
del list1[2]
list1[1]=str_temp2
list.append(list1)
print("最终行数据")
print(list1)
#list1.clear()
#print(list)
list_data=[]
for i in list: #已将尾日期数据合并成年月日 时分秒
list_data.append(merge(i))
del list_data[0] #删除文字表头
count=count-1 #删除了表头,总数据的行数减一
#print(list_data)
#list_temp=remove_Duplicates_list(list_data)[:] #将所有数据复制给临时列表list_temp 是去除重复后的列表
list_temp=list_data[:]
return count
def get_MorePages_teshu_shiqijia(url,page_num):
global sleeptime
global already_spider_datanum
urls=list_url(url,page_num) #得到需要遍历的页的url
count_all=0 #保存数据的总行数
list_all=[] #保存爬取的所有的数据
page=1
for i in urls:
count=0
count_all=count_all+get_OnePage_teshu_shiqijia(i,count)
if len(list_temp)==0: #如果该页为空,则表示该页后面都无数据 退出循环
print('后面页数为空,爬去下一个店铺')
break
list_all.extend(list_temp) #将列表追加到list_all中
print("爬取了第",page,"页")
page=page+1
print("\n")
time.sleep(sleeptime) #间隔2秒请求一次
for j in list_all:
print(j) #打印列表中每一行
print("总行数为:",count_all)
already_spider_datanum += count_all #已爬取数据的总和
return list_all
#-------------------------------------------------------------------------------------------------------------特殊的url
def get_OnePage_teshu(url,count): #抓取一页的数据,放入list_data中.urls为要访问的网页地址
# global ck
global list_temp #使用全局变量
list_temp.clear() #清空临时表
# session.headers = {
# # 此处注意cookie,要自己抓取
# # "Cookie":ck,
# "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36",
# }
r = session.get(url, verify=False).text
soup = bs(r,'html.parser')
list=[] #创建列表来保存结果
tags = soup.find_all("tr") # 列表所有行
for tag in tags: # 每个tag是一行
count=count+1
element = tag.text # 获取
标签内所有文本信息
element = element.strip() # 将字符串首尾空格去除
list1 = element.split(); # 以空格为分隔将字符串变为列表
del (list1[-2:]) #列表最后两个元素不需要,删除
print('删除特殊的后两个')
print(list1)
list.append(list1)
#list1.clear()
#print(list)
list_data=[]
for i in list:
list_data.append(merge(i)) #将尾日期数据合并成年月日 时分秒
del list_data[0] #删除文字表头
count=count-1 #删除了表头,总数据的行数减一
#print(list_data)
#list_temp=remove_Duplicates_list(list_data)[:] #将所有数据复制给临时列表list_temp 是去除重复后的列表
list_temp=list_data[:]
return count
def get_MorePages_teshu(url,page_num): #爬取指定店铺名的多页数据,pge_num表示爬取的页数
global sleeptime
global already_spider_datanum
urls=list_url(url,page_num) #得到需要遍历的页的url 返回该url对应页的所有链接形式,返回值为列表
count_all=0 #保存数据的总行数
list_all=[] #保存爬取的所有的数据
page=1
for i in urls:
count=0
count_all=count_all+get_OnePage_teshu(i,count)
if len(list_temp)==0: #如果该页为空,则表示该页后面都无数据 退出循环
print('后面页数为空,爬去下一个店铺')
break
list_all.extend(list_temp) #将列表追加到list_all中
print("爬取了第",page,"页")
page=page+1
print("\n")
time.sleep(sleeptime) #间隔2秒请求一次
for j in list_all:
print(j) #打印列表中每一行
print("总行数为:",count_all)
already_spider_datanum += count_all #已爬取数据的总和
return list_all
def spilt_url_teshu(con,page,date_begin=month_begin,date_end=now_date): #先对特殊的url做处理,再过滤
global already_spider_shopnum
global all_data
urls=url_more() #返回文件中所有店铺的url,带最大显示条数100 。urls是列表
#print(urls)
teshu_url=[]
#'shop=%25E9%25A3%259F%25E5%2585%25B6%25E5%25AE%25B6' 食其家
special_url=['shop=%25E4%25BA%25BA%25E7%2594%259F%25E4%25B8%2580%25E4%25B8%25B2','shop=%25E7%25BC%2598%25E5%25AE%25B6','shop=%25E4%25B8%25B0%25E8%258C%2582%25E7%2583%25A4%25E4%25B8%25B2','shop=%25E6%25B3%25B0%25E7%2585%258C%25E9%25B8%25A1','shop=%25E5%25B0%258F%25E9%2593%2581%25E5%2590%259B']
for url in urls: #遍历所有店铺的url
begin=url.find('&')+1
end=url.rfind('&')
#print(begin,end)
#找到特殊的url,进行特殊处理
if url[begin:end] in special_url:
print('发现特殊的!')
already_spider_shopnum += 1 #爬去的店铺数量加1
teshu_url.append(url)
#再删除一个列表元素
url_teshu=url_add_time(url,date_begin,date_end) #给所有url加上日期
list_to_MySql=get_MorePages_teshu(url_teshu,page) #店铺的url,爬取的页数
# a=remove_Duplicates_list(list_to_MySql)
# print('\n')
# for item in a:
# print(item)
if len(list_to_MySql) == 0 :
print('该家店铺时间段无数据,已跳过')
continue
has_remove_duplicates = remove_Duplicates_list(list_to_MySql) #去除某个店铺指定页数所有重复的数据
for item in has_remove_duplicates:
all_data.append(item)
# is_minutes_exceed_30(has_remove_duplicates,con) # 将指定页数的设备故障数据写入数据库异常表中
# isExceeding(has_remove_duplicates,con) # 将指定页数数据写入数据库超标表中
# ea_t_dev(has_remove_duplicates,con) # 将指定页数数据写入数据库设备信息表中
# fd_t_minbute(has_remove_duplicates,con) #将指定页数数据写入数据库分钟数据表中
list_to_MySql.clear()
if url[begin:end]=='shop=%25E9%25A3%259F%25E5%2585%25B6%25E5%25AE%25B6': #食其家
print('发现特殊的!')
already_spider_shopnum += 1 #爬去的店铺数量加1
teshu_url.append(url)
#再删除一个列表元素
url_teshu=url_add_time(url,date_begin,date_end) #给所有url加上日期
list_to_MySql=get_MorePages_teshu_shiqijia(url_teshu,page) #店铺的url,爬取的页数
# b=remove_Duplicates_list(list_to_MySql)
# for item in b:
# print(item)
if len(list_to_MySql) == 0 :
print('该家店铺时间段无数据,已跳过')
continue
has_remove_duplicates = remove_Duplicates_list(list_to_MySql) #去除某个店铺指定页数所有重复的数据
for item in has_remove_duplicates:
all_data.append(item)
# is_minutes_exceed_30(has_remove_duplicates,con) # 将指定页数的设备故障数据写入数据库异常表中
# isExceeding(has_remove_duplicates,con) # 将指定页数数据写入数据库超标表中
# ea_t_dev(has_remove_duplicates,con) # 将指定页数数据写入数据库设备信息表中
# fd_t_minbute(has_remove_duplicates,con) #将指定页数数据写入数据库分钟数据表中
list_to_MySql.clear()
for t in teshu_url: #从urls表中删除特殊的
urls.remove(t)
print(len(urls))
return urls
#-------------------------------------------------------------------------------------------------------------
def spider_all(con,page,date_begin=month_begin,date_end=now_date): #爬取文件中所有店铺(包括特殊的url店铺) 数据库连接对象 ,要爬取的页数,开始时间,结束时间
global already_spider_shopnum
global all_data
url_all=[]
#urls=url_more() #返回文件中所有店铺的url,带最大显示条数100
#做不符合的先处理
urls=spilt_url_teshu(con,page,date_begin,date_end)
for url in urls: #给所有url加上日期
url_all.append(url_add_time(url,date_begin,date_end))
for i in url_all: #打印最终的url
print(i)
for j in url_all: #根据所有url写入数据库
list_to_MySql=get_MorePages(j,page) #店铺的url,爬取的页数
already_spider_shopnum += 1 #爬去的店铺数量加1
# a=remove_Duplicates_list(list_to_MySql)
# print('\n\n')
# for item in a:
# print(item)
if len(list_to_MySql) == 0 :
print('该家店铺时间段无数据,已跳过')
continue
has_remove_duplicates = remove_Duplicates_list(list_to_MySql) #去除某个店铺指定页数所有重复的数据
for item in has_remove_duplicates:
all_data.append(item)
# is_minutes_exceed_30(has_remove_duplicates,con) # 将指定页数的设备故障数据写入数据库异常表中
# isExceeding(has_remove_duplicates,con) # 将指定页数数据写入数据库超标表中 写入异常表中
# ea_t_dev(has_remove_duplicates,con) # 将指定页数数据写入数据库设备信息表中
# fd_t_minbute(has_remove_duplicates,con) #将指定页数数据写入数据库分钟数据表中
list_to_MySql.clear()
def write_Sql(list,con): #将网站数据写入数据库
data = pd.DataFrame(list,columns=['provider','shop_name','equipment_number','equipment_name','smoke_push_density','smoke_pop_density','wind_turbine','purifier','level','alarm_required','alarm_triggered','attribution_time','reporting_time','data_time'])
print("\n\n")
print(data)
# test3 要写入的数据表,这样写的话要提前在数据库建好表
data.to_sql(name="ed_data", con=con, if_exists="append",index=False,index_label=False)
print("写入完成!")
# ck="" #保存cookie
session = requests.session()
webshops=[]
shopnum=0 #文件中店铺总数
already_spider_shopnum=0 #已爬取的店铺数量
already_spider_datanum=0 #已爬取的数据条数
sleeptime=8
Key_period_noon_begin = datetime.strptime('10:00',"%H:%M") #中午重点时段
Key_period_noon_end = datetime.strptime('14:00',"%H:%M")
Key_period_night_begin = datetime.strptime('17:00',"%H:%M") #晚上重点时段
Key_period_night_end = datetime.strptime('21:00',"%H:%M")
engine = create_engine("mysql+mysqlconnector://root:1234@localhost:3306/fume?charset=utf8")
# 专门读取设备信息表
con_read = engine.connect()
all_data = []
def pass_login(ses,beginTime,endTime,shops):
global con_read
# global ck
global session
global webshops
global all_data
global shopnum
global already_spider_shopnum
global already_spider_datanum
# 初始化 防止影响下次
all_data.clear()
shopnum=0
already_spider_shopnum=0
already_spider_datanum=0
# 初始化cookie 需要爬取的店铺名称
# ck = cookie
# 初始化session
session = ses
webshops = shops[:]
print('传入的店铺名称为:',shops)
engine = create_engine("mysql+mysqlconnector://root:1234@localhost:3306/fume?charset=utf8")
con = engine.connect()
# back_cookie() # 从文件中读取cookie
#爬取所有店铺 并计算耗时
start_time=time.time()
spider_all(con,100,beginTime,endTime) #爬取文件中所有的店铺名
# 给所有数据最后一个字段标记为‘0’
for item in all_data:
item.append(0)
end_time=time.time()
# duration = round(end_time-start_time,2)
# 关闭数据库连接
con_read.close()
con.close()
print("获取数据完成!")
print("设置获取的时间间隔为",sleeptime,"秒")
print("共有",shopnum,"家","已获取",already_spider_shopnum,"家")
print("共获取",already_spider_datanum,"条记录")
print("共耗时:{:.2f}秒".format(end_time-start_time))
result=[]
result.append('获取数据完成!')
result.append("共有"+str(shopnum)+"家,已获取"+str(already_spider_shopnum)+"家")
result.append("共获取"+str(already_spider_datanum)+"条记录")
result.append("共耗时:{:.2f}秒".format(end_time-start_time))
return result,all_data
# pass_login()