新建一个项目 Windows:打开cmd,输入: pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy
直接调用scrapy 这个库
scrapy startproject 你要创建文件名称
这样子创建文件夹的工程就好了
创建爬虫
创建爬虫的py文件
scrapy genspider 爬虫名称 这个是网址
看到Created spider就代表创建成
ubantu终端启动pycharm
启动 直接键入即可
你新建完之后直接打开,然后里面有一个hotel_scrapy你键 的文件直接在这里面写代码就可以了
写完代码启动程序 要到你创建的文件目录下启动
数据爬取 import pandas as pd import scrapy import os class HotelSpiderSpider(scrapy.Spider): name = "hotel_spider" allowed_domains = ["172.16.7.8"] # 采集地址 base_url = "http://172.16.7.8" # 页码从第一页开始 start_page = 1 # 生产起始的url,先从城市开始 def start_requests(self): for city_id in range(1,4): # yield scrapy.Request:是一个固定的方法 self是一个方法 # 一个个去请求 city_id是城市 start_page是页码 # callback=self.parse_first_page:把拿回来的数据给parse_first_page来处理 # meta={'cityId':city_id}:再把city_id传递 yield scrapy.Request(f'{self.base_url}/?cityId={city_id}&pageNum={self.start_page}',callback=self.parse_first_page,meta={'cityId': city_id}) # 处理每个城市的首页,主要用来获取页数 def parse_first_page(self,response): # 提取酒店的信息 # 把所有包含card-body类的duv全部拿回来 hotels = response.css('div.card-body') # 城市 cityid = response.meta['cityId'] # 解析页码 for hotel in hotels: # 酒店名称 hotel_name = hotel.css('h5.card-title a::text').get() # 城市名 city = '' if cityid == 1: city = '北京' elif cityid == 2: city = '上海' elif cityid == 3: city = '广州' elif cityid == 4: city = '深圳' # 星级 start = len(hotel.xpath('p[1]//i').getall()) # 评分 # [4:]从第四个开始取后面的数据 rating = hotel.xpath('p[3]//text()').get()[4:] # 获取详情页的信息 detail_url = hotel.css('h5.card-title a::attr(href)').get() # 获取数据并且处理 yield scrapy.Request(f'{self.base_url}{detail_url}',callback=self.parse_detail,meta={'hotel_name': hotel_name, 'city': city, 'start': start, 'rating': rating}) # 获取页码 # [-2]从倒数第二个开始取 int:转换数字类型 last_page_num_text = int(response.css('a.page-link::text')[-2].get()) # 生产每一页的url(从第二页开始,到最后一页) for page_num in range(self.start_page+1,last_page_num_text+1): url = f'{self.base_url}/?cityId={cityid}&pageNum={page_num}' # 调用一个处理程序 yield scrapy.Request(url, callback=self.parse, meta={'cityId': cityid}) # 提取酒店的信息 def parse(self, response): # 把所有包含card-body类的duv全部拿回来 hotels = response.css('div.card-body') # 城市 cityid = response.meta['cityId'] # 解析页码 for hotel in hotels: # 酒店名称 hotel_name = hotel.css('h5.card-title a::text').get() # 城市名 city = '' if cityid == 1: city = '北京' elif cityid == 2: city = '上海' elif cityid == 3: city = '广州' elif cityid == 4: city = '深圳' # 星级 start = len(hotel.xpath('p[1]//i').getall()) # 评分 # [4:]从第四个开始取后面的数据 rating = hotel.xpath('p[3]//text()').get()[4:] # 获取详情页的信息 detail_url = hotel.css('h5.card-title a::attr(href)').get() # 获取数据并且处理 yield scrapy.Request(f'{self.base_url}{detail_url}', callback=self.parse_detail,meta={'hotel_name': hotel_name,'city': city,'start': start,'rating': rating}) # 酒店的基本信息 def parse_detail(self,response): # 把数据取再拿出来一下 hotel_name = response.meta['hotel_name'] city = response.meta['city'] start = response.meta['start'] rating = response.meta['rating'] # 房间数量 rooms = 0 hotel_room_num = response.xpath('//*[@id="room-types"]//div/p[2]/span//text()').getall() for room_num in hotel_room_num: rooms = rooms + int(room_num.strip()) # strip清除前后空白字符 # 图片数量 images = len(response.xpath('//*[@id="room-types"]//div/img').getall()) # 评论数量 comments = len(response.css('div.user-comment')) # 把采集到的数据保存到DataFrame data = {'酒店名称': [hotel_name], '城市': [city], '星级': [start], '评分': rating,'房间数': [hotel_room_num] ,'图片数': [images], '评论数': [comments]} df = pd.DataFrame(data) # 判断csv是否存在,不存在就新建,存在就追加 if not os.path.isfile('hotel.csv'): df.to_csv('hotel.csv',index=False) else: # mode='a':追加 header=False:不需要表头 df.to_csv('hotel.csv', mode='a', header=False, index=False)
数据分析处理 重新新建一个python环境 import pandas as pd # 读取 hotel2.csv文件 df = pd.read_csv('hotel2.csv',encoding='utf-8') # 删除酒店名称为空的,并且保存3为hotel2_c1.csv df_c1 = df.dropna(subset=['酒店名称']) df_c1.to_csv('hotel2_c1.csv',index=False,encoding='utf-8') # 删除缺失大于3个的记录,并且保存hotel2_c2.csv, shape[1]用来计算列的数量 df_c2 = df.dropna(thresh=df.shape[1]-3) df_c2.to_csv('hotel2_c2.csv',index=False,encoding='utf-8') # 将评分为空的填0并且保存hotel2_c3.csv # copy:拷贝一个 df_c3 = df.copy() df_c3['评分'] = df_c3['评分'].fillna(0) # fillna:把空的单元格填上什么值 df_c3.to_csv('hotel2_c3.csv',index=False,encoding='utf-8') # 评分为空的填平均值并且保存hotel2_c4.csv df_c4 = df.copy() # df_c4['评分'].mean()用来保存的数据为平均分 df_c4['评分'] = df_c4['评分'].fillna(df_c4['评分'].mean()) df_c4.to_csv('hotel2_c4.csv',index=False,encoding='utf-8') # 删除缺失大于3个的记录,并且保存hotel2_c2.csv, shape[1]用来计算列的数量 df_c2 = df.dropna(thresh=df.shape[1]-3) df_c2.to_csv('hotel2_c2.csv',index=False,encoding='utf-8')