选题背景
现阶段随着经济的大发展,人们开始逐渐注重丰富自己的闲暇时光,以达到闲情逸致的目的,旅游也因此成为了人们丰富生活的方法之一。但由于旅游景点非常之多,水平也参差不齐,再加以人们休息的时间并不足以支持游玩所有的景点。因此我通过此次的爬虫技术查看当地旅游景点,并通过数据分析对当地旅游景点进行排名,以达到优先选择最受欢迎的景点的目的。
选题意义
随着网络的迅速发展,万维网成为大量信息的载体,如何有效地提取并利用这些信息成 为一个巨大的挑战。搜索引擎(例如传统的通用搜索引擎AltaVista,Yahoo!和Google等)作 为一个辅助人们检索信息的工具成为用户访问万维网的入口和指南。但是,这些通用性搜索 引擎也存在着一定的局限性,如:
(1)不同领域、不同背景的用户往往具有不同的检索目的和需求,通用搜索引擎所返回的结果包含大量用户不关心的网页。
(2)通用搜索引擎的目标 是尽可能大的网络覆盖率,有限的搜索引擎服务器资源与无限的网络数据资源之间的矛盾将 进一步加深。
(3)万维网数据形式的丰富和网络技术的不断发展,图片、数据库、音频/视 频多媒体等不同数据大量出现,通用搜索引擎往往对这些信息含量密集且具有一定结构的数 据无能为力,不能很好地发现和获取。
(4)通用搜索引擎大多提供基于关键字的检索,难以支持根据语义信息提出的查询。为了解决上述问题,定向抓取相关网页资源的聚焦爬虫应运 而生。聚焦爬虫是一个自动下载网页的程序,它根据既定的抓取目标,有选择的访问万维网 上的网页与相关的链接,获取所需要的信息。与通用爬虫(generalpurpose web crawler)不同,聚焦爬虫并不追求大的覆盖,而将目标定为抓取与某一特定主题内容相关的网页,为面 向主题的用户查询准备数据资源。
这次选取的旅游景点的网站,一方面达到自己学习爬虫,利用网络技术爬取信息的目的,另一方面可以通过此次爬虫帮助人们优先选择最受欢迎的景点,避免浪费休息时间,游玩自己不喜欢的景点。通过最短的时间选择到自己喜欢的景点,了解到景点的介绍、开放时间,以达到合理安排时间的目的。
课题实现相关技术
-
Python语言
Python是一种解释型,面对对象的高级程序设计语言,功能强大,具有简单、高级、面向对象、开源免费、可移植性、可扩展性等特点。
Python是一门跨平台、开源、免费的解释型动态编程语言。
Python支持命令式编程(How to do)、函数式编程(What to do),完全支持面向对象程序设计。
Python标准库非常大,可以处理各种工作。
Python语言具有良好的可扩展性 -
Requests库
requests 模块是 python 基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库。
通过pip install requests或者conda requests方法安装 -
Scrapy爬虫框架
Scrapy框架是一个基于Python语言开发的爬虫框架,他具有非常丰富的配置选项,可以针对反扒力度不同的网站设置不同的反反爬策略,且Scrapy爬虫框架是多线程的。可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中。
Scrapy主要有五大核心组件:引擎(Scrapy Engine)、调度器(Scheduler)、下载器(Downloer)、爬虫器(Spiders)、项目管道(Item Pipeline)。
引擎是整个框架的核心,负责控制数据流在系统中所有组件间流动。
调度器从引擎接受Request并将它们放入一个网络请求队列,以便在引擎请求时提供给引擎。
下载器是实际Http请求的真正执行者,完成网络请求工作。
爬虫器负责构造Request并作为方法的返回值返回给引擎 -
xpath选择器
xpath是一套用于解析XML/HTML的语法,它使用路径表达式来选取XML/HTML中的节点或节点集。
课题实现
建立scrapy框架
二、北京热门景点排行标题页
要爬取的信息是:景点名称、景点地址、景点的评分。
三、热门景点详情页
要爬取的信息是景点的介绍和开放时间。
四、爬虫代码
import scrapy
from ..items import AttractionItems
class SpotSpider(scrapy.Spider):
name = 'spot'
start_urls = ['https://you.ctrip.com/sight/beijing1.html']
def parse(self, response, **kwargs):
# 景点名称定位
places = response.xpath('//div[@class="rdetailbox"]/dl/dt/a[@target="_blank"]/text()').extract()
# 景点地址定位
addresss = response.xpath('//div[@class="normalbox"]//div[@class="rdetailbox"]/dl/dd/text()').extract()
# addresss = [address.strip()for address in addresss]
# address = "".join(addresss)
# 景点评分定位
scores = response.xpath('//div[@class="normalbox"]//div[@class="rdetailbox"]/ul/li/a/strong/text()').extract()
# 景点详情页链接定位
detail_pages = response.xpath('//div[@class="normalbox"]//div[@class="rdetailbox"]/dl/dt/a/@href').extract()
for ind, detail_page in enumerate(detail_pages):
try:
place = places[ind]
address = addresss[ind]
score = scores[ind]
except:
continue
yield scrapy.Request(detail_page, callback=self.parse_detail,
meta={"place": place, "address": address, "score": score})
next_page = response.xpath('//div[@class = "pager_v1"]/a[@class = "nextpage"]/@href').extract_first()
base_url = 'https://you.ctrip.com'
if next_page:
yield scrapy.Request(url=base_url + next_page, callback=self.parse, dont_filter=True)
def parse_detail(self, response):
# 调用strip()方法,去除字符串前后的空格,并将字符串列表转换成完整的字符串
comments = response.xpath(
'//div[@class = "detailModuleRef"]//div[@class="LimitHeightText"]/div/p/text()').extract()
comments = [comment.strip() for comment in comments]
comment = "".join(comments)
times = response.xpath('//div[@class = "detailModuleRef"]/div/div[@class="moduleContent"]/text()').extract()
times = [time.strip() for time in times]
time = "".join(times)
place = response.meta['place']
address = response.meta['address']
score = response.meta['score']
print(place, address, score, comment, time)
# print("地点:", meta["place"])
# print("地址:", meta["address"])
# print("评分:", meta["score"])
# print("介绍:", comment)
# print("开放时间:", time)
item = AttractionItems()
item['place'] = place
item['address'] = address
item['score'] = score
item['comment'] = comment
item['time'] = time
yield item
整体思路:
- 获取热门景点排行标题页中热门景点名称、地址和评分的Xpath路径,观察不同位置的信息Xpath路径知否具有规律,在获取规律之后将Xpath路径写入。
五、反反爬虫策略
-
模拟自然人的访问频率:
通过设置爬取间隔和并发爬取量来模拟自然人的访问频率 -
通过自定义User-Agent来伪装成浏览器访问
建立User-Agent池,随机选择一组User-Agent
六、保存下来的文件
通过在item文件中引入AttractionItem类达到获取数据保存文件的目的