新建一个项目

Windows:打开cmd,输入:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple scrapy
mkdir 文件夹名称
cd 到你刚创建的文件夹

直接调用scrapy这个库

scrapy startproject 你要创建文件名称

这样子创建文件夹的工程就好了

创建爬虫

cd 到你刚刚新建的目录

创建爬虫的py文件

scrapy genspider 爬虫名称 这个是网址

看到Created spider就代表创建成

ubantu终端启动pycharm

cd 到你的pycharm的根目录

启动
直接键入即可

./pycharm.sh

你新建完之后直接打开,然后里面有一个hotel_scrapy你键 的文件直接在这里面写代码就可以了

写完代码启动程序

要到你创建的文件目录下启动

scrapy crawl 程序名称

数据爬取

 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')