《Python程序语言基础》期末课程设计
(2020-2021学年第二学期)
学生姓名: 库洛
提交日期:2021年 7月2日
学 号 座位编号
学 院 电子与信息学院 专业班级 信息工程5班
课程名称 Python程序语言基础 任课教师 田 翔
教师评语:
本论文成绩评定: 分
目 录
一、系统功能设计21、系统描述22、对象清单23、类设计2二、主要流程设计31、Scrapy框架构成:3(1)、调度器(Scheduler):4(2)、下载器(Downloader):4(3)、 爬虫(Spider):4(4)、 实体管道(Items Pipeline):4(5)、引擎(Scrapy Engine):4(6)、下载器中间件(Downloader Middlewares):4(7)、爬虫中间件(Spider Middlewares):4(8)、调度中间件(Scheduler Middewares):42、scrapy详细工作流程5三、前端界面设计6四、后台数据库设计6五、核心算法流程图7六、使用手册71、爬虫运行方法72、数据查看及处理8七、核心功能源代码101、tpy.py102、items.py123、pipelines.py13
太平洋汽车网评论爬虫
一、系统功能设计
1、系统描述
本爬虫基于scrapy框架,可以完成对太平洋汽车网用户评论的全自动爬取,包括两层循环的翻页,爬行逻辑为先翻页爬取某车型的所有评论,再翻页爬取其他车型评论,且根据网站总编码爬行,理论上可以爬取太平洋汽车网所有评论内容。
其中,使用User-Agent轮转,禁用cookies,降低被封几率,降低下载延时,提高下载速度,提升爬取效率。
爬取的评论信息内容包括车主昵称、发布时间、购买车型、裸车价格/万元,以及评论的具体分项,如优点、缺点、外观、内饰、空间、配置、动力、越野、油耗、舒适。前端用户通过Excel表格查看爬取内容,可按品牌、具体车型,价格区间等多种方式进行相关商品的搜索、筛选、查询、对比等。默认为总览模式,如需查看完整内容只需把自动换行打开即可。
2、对象清单
本爬虫由以下几个模块组成,功能设计如下:
tpy.py 爬虫总文件,决定爬虫运行逻辑
items.py 项目文件,编写爬虫的爬取项目
pipelines.py 管道文件,设计爬虫数据下载和储存
settings.py 设置文件,设置scrapy爬取参数
middlewares.py 下载中间件,主要用于设置UA轮转
run.py 启动爬虫,用于代替命令行方式启动
crawl.py 官方启动方式,主要用于封装
scrapy.cfg scrapy启动必备组件
generate_cfg.py 用于运行时生成scrapy.cfg方便封装
mime.types scrapy组件,用于封装
VERSION scrapy组件,用于封装
3、类设计
tpy.py
class TpySpider(scrapy.Spider) 爬虫类,获取开始值和结束值用于限制爬行范围,设置start_urls确定爬虫起始爬取地址。
def parse(self, response) 提取response中特定字段信息,通过xpath按层查找所需信息。爬取翻页设计,包括大小两层循环,小翻页为同种型号汽车的多页评论爬取,大翻页为不同型号汽车的评论爬取。
items.py
class TpyspiderItem(scrapy.Item) 确定爬取每个内容的具体项目名称
pipelines.py
class TpyspiderPipeline(object) 爬取管道设计
def __init__(self) 创建CSV文件并输入第一行中文标题
def process_item(self, item, spider) 将爬取内容写入CSV文件
def close_spider(self, spider) 爬虫关闭函数,关闭时顺带关闭保存CSV文件,之后.csv转.xlsx文件并调整列宽直接覆盖
middlewares.py
class MyUserAgentMiddleware(UserAgentMiddleware) 设置User-Agent轮转
二、主要流程设计
1、Scrapy框架构成:
Scrapy框架主要由五大组件组成,它们分别是调度器(Scheduler)、下载器(Downloader)、爬虫(Spider)和实体管道(Items Pipeline)、引擎(Scrapy Engine)。此外还有各种中间件,如下载器中间件(Downloader Middlewares)、爬虫中间件(Spider Middlewares)、调度中间件(Scheduler Middewares),下面我们分别介绍各个组件的作用。
、调度器(Scheduler):
调度器,用来接受引擎发过来的请求, 压入队列中, 并在引擎再次请求的时候返回. 可以想像成一个URL(抓取网页的网址或者说是链接)的优先队列, 由它来决定下一个要抓取的网址是什么, 同时去除重复的网址用户可以自己的需求定制调度器。
、下载器(Downloader):
下载器,是所有组件中负担最大的,它用于高速地下载网络上的资源,并将网页内容返回给蜘蛛。Scrapy的下载器代码不会太复杂,但效率高,主要的原因是Scrapy下载器是建立在twisted这个高效的异步模型上的(其实整个框架都在建立在这个模型上的)。
、 爬虫(Spider):
爬虫,是用户最关心的部份。用户定制自己的爬虫(通过定制正则表达式等语法),用于从特定的网页中提取自己需要的信息,即所谓的实体(Item)。 用户也可以从中提取出链接,让Scrapy继续抓取下一个页面。
、 实体管道(Items Pipeline):
实体管道,负责处理爬虫从网页中抽取的实体,主要的功能是持久化实体、验证实体的有效性、清除不需要的信息。当页面被爬虫解析后,将被发送到项目管道,并经过几个特定的次序处理数据。
、引擎(Scrapy Engine):
引擎是整个框架的核心.它用来控制调试器、下载器、爬虫,进行整个系统的数据流处理, 触发事务。实际上,引擎相当于计算机的CPU,它控制着整个流程。
、下载器中间件(Downloader Middlewares):
位于Scrapy引擎和下载器之间的框架,主要是处理Scrapy引擎与下载器之间的请求及响应。
、爬虫中间件(Spider Middlewares):
介于Scrapy引擎和爬虫之间的框架,主要工作是处理蜘蛛的响应输入和请求输出。
、调度中间件(Scheduler Middewares):
介于Scrapy引擎和调度之间的中间件,从Scrapy引擎发送到调度的请求和响应。
2、scrapy详细工作流程
、首先Spiders(爬虫)将需要发送请求的url(requests)经ScrapyEngine(引擎)交给Scheduler(调度器)。
、Scheduler(排序,入队)处理后,经ScrapyEngine,DownloaderMiddlewares(可选,主要有User_Agent, Proxy代理)交给Downloader。
、Downloader向互联网发送请求,并接收下载响应(response)。将响应(response)经ScrapyEngine,SpiderMiddlewares(可选)交给Spiders。
、Spiders处理response,提取数据并将数据经ScrapyEngine交给ItemPipeline保存(可以是本地,可以是数据库)。
、提取url重新经ScrapyEngine交给Scheduler进行下一个循环。直到无Url请求程序停止结束。
三、前端界面设计
用户操作前端界面为爬虫启动时的黑框界面和数据处理时的Excel界面,具体内容在使用手册中介绍。
四、后台数据库设计
爬取数据生成 缓存.csv文件,爬虫关闭时,.csv转.xlsx并调整列宽覆盖,生成 ^爬虫数据.xlsx文件(自动根据开始值和结束值命名)。
五、核心算法流程图
六、使用手册
1、爬虫运行方法
爬虫运行开始值与结束值范围大概在 6-30000 之间(前5个是空的,30000之后爬了4000个网页没有数据,可以认为之后的是空的,中间也有一大堆空的,遇到多半报404或503错误,已设置报错选项,忽略报错继续爬行),运行方法从以下任选一种即可。
1.1 双击封包之后生成的 .*.exe文件(推荐),填入开始值和结束值运行爬虫。
这个方法可以将 .*.exe文件 放到任何一台计算机上使用,而无需环境支持,运行时自动生成scrapy.cfg文件(scrapy框架运行所需)、缓存.csv文件,爬虫关闭时,.csv转.xlsx并调整列宽覆盖,生成 ^爬虫数据.xlsx文件(自动根据开始值和结束值命名)。
ps.如需多次使用爬虫,请在开始之前将缓存.csv删除,否则新数据会添加在旧数据后,最后全部写入 ^爬虫数据.xlsx文件
1.2 双击 crawl.py 或 run.py 以Python方式打开爬虫,填入开始值和结束值运行爬虫。
此方法需要Python环境,scrapy框架,以及所有爬虫里import的包的支持。
1.3 使用pycharm打开crawl.py 或 run.py,可以检查并补充缺失的环境变量,crawl.py 和 run.py实现的功能一致,不过方法不同:crawl.py是官方的scrapy启动方法,run.py实际上是命令行方法。
1.4 命令行方法:在爬虫目录打开cmd,输入命令 scrapy crawl tpy ,填入开始值和结束值运行爬虫。
此方法需要Python环境,scrapy框架,以及所有爬虫里import的包的支持。
运行截图如下:
2、数据查看及处理
打开^爬虫数据.xlsx文件,里面记录了爬取的评论信息,包括车主昵称、发布时间、购买车型、裸车价格/万元,以及评论的具体分项,如优点、缺点、外观、内饰、空间、配置、动力、越野、油耗、舒适。前端用户可按品牌、具体车型,价格区间等多种方式进行相关商品的搜索、筛选、查询、对比等。默认为总览模式,如需查看完整内容只需把自动换行打开即可。
运行截图:
筛选价格区间:
品牌筛选:
发布时间排序:
具体评论内容查看:
七、核心功能源代码
运行环境:win10-64位 编程语言: Python
编译器:Python 3.8(Python-3.9.4)
1、tpy.py
import scrapy
from scrapy.http import Request
from ..items import TpyspiderItem
class TpySpider(scrapy.Spider):
name = 'tpy'
allowed_domains = ['www.pcauto.com.cn']
handle_httpstatus_list = [404, 503]
page = 1
start = int(input("请输入开始值:"))
stop = int(input("请输入结束值:"))
offset = start
start_urls = ['https://price.pcauto.com.cn/comment/sg{}/t1/p1.html'.format(str(offset))]
print(start_urls)
def parse(self, response):
"""
@params:response,提取response中特定字段信息
"""
items = TpyspiderItem()
lists = response.xpath('//div[@class="litDy clearfix"]')
for i in lists:
items['cznc'] = i.xpath('.//div[@class="txBox"]/div[1]/p/a/text()').extract()
items['fbsj'] = i.xpath('.//div[@class="txBox"]/div[1]/span/a/text()').extract()
items['gmcx'] = i.xpath('.//div[@class="txBox"]/div[2]/a/text()').extract()
items['lcjg'] = i.xpath('.//div[@class="txBox"]/div[6]/i/text()').extract()
items['yd'] = i.xpath('.//div[@class="dianPing clearfix"]/div[1]/span/text()').extract()
items['qd'] = i.xpath('.//div[@class="dianPing clearfix"]/div[2]/span/text()').extract()
items['wg'] = i.xpath('.//div[@class="dianPing clearfix"]/div[3]/span/text()').extract()
items['ns'] = i.xpath('.//div[@class="dianPing clearfix"]/div[4]/span/text()').extract()
items['kj'] = i.xpath('.//div[@class="dianPing clearfix"]/div[5]/span/text()').extract()
items['pz'] = i.xpath('.//div[@class="dianPing clearfix"]/div[6]/span/text()').extract()
items['dl'] = i.xpath('.//div[@class="dianPing clearfix"]/div[7]/span/text()').extract()
items['yy'] = i.xpath('.//div[@class="dianPing clearfix"]/div[8]/span/text()').extract()
items['yh'] = i.xpath('.//div[@class="dianPing clearfix"]/div[9]/span/text()').extract()
items['ss'] = i.xpath('.//div[@class="dianPing clearfix"]/div[10]/span/text()').extract()
yield items
if self.offset < self.stop:
if response.xpath('//a[@class="next"]'):
# 小翻页,同种型号汽车的多页评论爬取
self.page += 1
url = 'https://price.pcauto.com.cn/comment/sg{}/t1/p{}.html'.format(str(self.offset), str(self.page))
print(url)
yield Request(url=url, callback=self.parse, dont_filter=True)
else:
# 大翻页,不同型号汽车的评论爬取
self.page = 1
self.offset += 1
url = 'https://price.pcauto.com.cn/comment/sg{}/t1/p1.html'.format(str(self.offset))
print(url)
yield Request(url=url, callback=self.parse, dont_filter=True)
# dont_filter=True,忽略allowed_domains的过滤
# 为了防止二次解析的域名被过滤掉,否则 DEBUG: Filtered offsite request to
2、items.py
import scrapy
class TpyspiderItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 车主昵称
cznc = scrapy.Field()
# 发布时间
fbsj = scrapy.Field()
# 购买车型
gmcx = scrapy.Field()
# 裸车价格/万元
lcjg = scrapy.Field()
# 优点
yd = scrapy.Field()
# 缺点
qd = scrapy.Field()
# 外观
wg = scrapy.Field()
# 内饰
ns = scrapy.Field()
# 空间
kj = scrapy.Field()
# 配置
pz = scrapy.Field()
# 动力
dl = scrapy.Field()
# 越野
yy = scrapy.Field()
# 油耗
yh = scrapy.Field()
# 舒适
ss = scrapy.Field()
3、pipelines.py
import csv
import os
import pandas as pd
from openpyxl import load_workbook
import tpyspider.spiders.tpy
class TpyspiderPipeline(object):
start = tpyspider.spiders.tpy.TpySpider.start
stop = tpyspider.spiders.tpy.TpySpider.stop
def __init__(self):
# csv文件的位置,无需事先创建
store_file = os.path.dirname(os.path.abspath("__file__")) + '/缓存.csv'
# store_file = os.path.dirname(__file__) + '/spiders/tpy.csv'
# 打开(创建)文件
self.file = open(store_file, 'a+', encoding="utf-8", newline='')
# csv写法
self.writer = csv.writer(self.file, dialect="excel")
self.header = ['车主昵称', '发布时间', '购买车型', '裸车价格/万元', '优点', '缺点', '外观', '内饰', '空间', '配置', '动力', '越野', '油耗', '舒适']
self.a = ['cznc', 'fbsj', 'gmcx', 'lcjg', 'yd', 'qd', 'wg', 'ns', 'kj', 'pz', 'dl', 'yy', 'yh', 'ss']
self.csvWrite = csv.DictWriter(self.file, fieldnames=self.header)
self.csvWrite.writeheader()
def process_item(self, item, spider):
temp = {}
self.csvWrite = csv.DictWriter(self.file, fieldnames=self.a)
for column in self.a:
temp[column] = ''.join(item[column])
self.csvWrite.writerow(temp)
return item
def close_spider(self, spider):
name = "爬虫数据" + str(self.start) + "-" + str(self.stop)
# 关闭爬虫时顺便将文件保存退出
self.file.close()
csv1 = pd.read_csv(os.path.dirname(os.path.abspath("__file__")) + '/缓存.csv', encoding='utf-8')
csv1.to_excel(os.path.dirname(os.path.abspath("__file__")) + '/' + name + '.xlsx', sheet_name='data', index=False)
# index=False,.csv转.xlsx时去掉自动序号
# 修改列宽
# path = 'tpy.xlsx'
# 上一行可以在pycharm内运行,不过直接运行run.py无法找到tpy.xlsx,故改成下一行完整写法
# path = os.path.dirname(__file__) + '/spiders/tpy.xlsx'
path = os.path.dirname(os.path.abspath("__file__")) + '/' + name + '.xlsx'
wb = load_workbook(path)
ws = wb.active
ws.column_dimensions['A'].width = 25
ws.column_dimensions['B'].width = 11
ws.column_dimensions['C'].width = 55
ws.column_dimensions['D'].width = 15
for i in range(5, 15):
ws.column_dimensions[chr(64 + i)].width = 50 # A是65
wb.save(name + '.xlsx')
# 修改列宽后直接覆盖
————————————————
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/m0_66999594/article/details/139582246