Scrapy 爬取旅游景点相关数据(五)

本期内容:(1)爬取日本其他城市数据存入数据库(2)爬取景点评论数据

1 爬取其他城市景点数据

只爬取一个城市的数据对于做数据可视化系统可能是不够的,因为数据样本量少嘛,本期来爬取其他城市的景点数据,前面四期已经打好的良好基础,本期内容非常简单,只需要对项目稍加修改,就可以完成,废话不多说,let’s go。

首先改一下爬虫,把城市作为一个参数,比如现在改为横滨:

start_urls = ['https://place.qyer.com/yokohama/sight/']
city = '横滨'
nation = '日本'

item部分这样写:

item['city'] = self.city
item['nation'] = self.nation

翻页的时候判断下100页以上的不用爬取了,因为这个网站超过100页你去点下一页,它也不刷新数据了

            if page_number > 100:break

多爬一些数据,后续做旅游分析系统的时候数据多一点系统做出来就好看,我爬取的结果:

在这里插入图片描述

2 爬取评论数据 爬取思路

之前爬取的数据字段里有个comment_url ,就是为了爬取评论数据作的准备,通过这个字段就可以爬取每个景点的用户评论,例如东京迪士尼景区的用户评论是在这个地址:https://place.qyer.com/poi/V2EJalFnBzRTbQ/review/

通过浏览器的开发者模式可以大致如何爬取这个页面,其他也类似于景区列表,这个页面也是通过翻页来加载数据的。

下面用一张图来展示爬取流程:

在这里插入图片描述

首先需要遍历tb_tour表的comment_url字段,循环中去读取每个景点的评论页面, 而爬取评论页面的过程中需要翻页,这里面也涉及一个循环,爬取每页都会去调用一次pipeline进行数据的存储。

这次我们会有两个地方去读取mysql数据库,一个是爬虫,二是管道部分,因此先优化一下数据库的配置,把链接信息写到settings.py里


DB_HOST = 'localhost'
DB_USER = '******'
DB_PASS = '******'
DB_DATABASE = 'scrapy_demo'
DB_CHARSET  = 'utf8'

3 编写评论爬虫 初始化部分

首先新建一个爬虫QyCommentSpider ,整个整体的思路和之前爬取景点的类似,不同之处在于启动的Url需要从数据库里去获取,另外,需要一个专门的管道了处理数据。先编写部分爬虫

class QyCommentSpider(scrapy.Spider):name = 'cmt'custom_settings = {'ITEM_PIPELINES': {'tutorial2.pipelines.TourCommentPipeline': 300}}def __init__(self, *args, **kwargs):super(QyCommentSpider, self).__init__(*args, **kwargs)options = webdriver.ChromeOptions()# 这行代码是用于设置 Chrome 浏览器的选项。--headless 参数表示以无头模式(无 GUI 界面)运行 Chrome 浏览器。# 无头模式下,浏览器运行在后台,不会显示任何图形界面,从而能够提高爬取效率和性能。这在服务器环境中非常有用,因为服务器通常没有图形界面。options.add_argument('--headless')LOGGER.setLevel(logging.WARNING)# 这行代码是用于指定 ChromeDriver 的路径。ChromeDriver 是 Selenium 用于控制 Chrome 浏览器的驱动程序。service = Service('/usr/local/bin/chromedriver')self.driver = webdriver.Chrome(options=options, service=service)  # 替换为 ChromeDriver 的实际路径def start_requests(self):# 连接 MySQL 数据库db = pymysql.connect(host=self.settings.get('DB_HOST'),user=self.settings.get('DB_USER'),password=self.settings.get('DB_PASS'),database=self.settings.get('DB_DATABASE'),charset=self.settings.get('DB_CHARSET'))cursor = db.cursor()cursor.execute("SELECT comment_url, id FROM tb_tour")start_urls = cursor.fetchall()cursor.close()db.close()for url in start_urls:yield scrapy.Request(url=url[0], callback=self.parse,meta={'tid': url[1]})

4 编写item 和 管道

class TourCommentItem(scrapy.Item):tid = scrapy.Field()username = scrapy.Field()avatar = scrapy.Field()comments = scrapy.Field()# 保存mysql 景点评论
class TourCommentPipeline:def process_item(self, item, spider):pass

在settings里也增加下新的管道

ITEM_PIPELINES = {'tutorial2.pipelines.TourPipeline': 300,'tutorial2.pipelines.TourCommentPipeline': 301,
}

5 解析代码 【补充】

做视频的时候发现漏了给出解析的代码了,下面补全

 def parse_page(self, page_source, tid):response = scrapy.Selector(text=page_source)# 生成指纹fingerprint = self.get_fingerprint(page_source)# 判断指纹是否存在if self.fingerprint_exists(fingerprint):self.logger.info('指纹已存在,跳过 %s', fingerprint)return# 保存指纹self.save_fingerprint(fingerprint)# print(response)comments = response.xpath('//ul[@id="commentlist"]/li')# print('comments=', comments)for comment in comments:item = TourCommentItem()item['tid'] = tiditem['username'] = comment.xpath('.//a/span/text()').get().strip()item['avatar'] = comment.xpath('.//a/img/@src').get().strip()item['comments'] = comment.xpath('.//div[@class="comment clearfix"]/p[@class="content"]').xpath('string(.)').extract()[0]print(f"\033[36m{item['tid']}\033[0m")print(f"\033[92m{item['username']}\033[0m")# print(f"\033[92m{item['avatar']}\033[0m")# print(f"\033[92m{item['comments']}\033[0m")yield item

6 开启debug

之前我们一直是用命令行来跑scrapy 的,可以在scrapy.cfg同级目录建一个run.py文件

# -*- coding:utf-8 -*-
from scrapy import cmdline
# cmt 对应的是爬虫名
# 在cmd运行 scrapy crawl cmt 同步
cmdline.execute("scrapy crawl cmt".split())

pycharm去执行这个文件,就可以debug运行了。

爬取结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/391184.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

等保测评练习卷25

等级保护初级测评师试题25 姓名: 成绩: 一、判断题(10110分) 1.安全区域边界对象主要根据系统中网络访问控制设备的部署情况来确定()不是网络访问控制设备而…

笔试练习day2

目录 BC64 牛牛的快递题目解析解法模拟代码方法1方法2 DP4 最小花费爬楼梯题目解析解法动态规划状态表示状态转移方程代码 数组中两个字符串的最小距离题目解析解法方法1暴力解法(会超时)方法2贪心(动态规划)代码 感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接…

Yolov8在RK3588上进行自定义目标检测(一)

1.数据集和训练模型 项目地址:https://github.com/airockchip/ultralytics_yolov8.git 从github(htps:l/github.com/airockchip/ultralytics_yolov8)上获取yolov8模型。 下载项目: git clone https://github.com/airockchip/ultralytics_yolov8.git …

Python | Leetcode Python题解之第316题去除重复字母

题目: 题解: class Solution:def removeDuplicateLetters(self, s: str) -> str:vis defaultdict(int)cnt defaultdict(int)for ch in s: cnt[ch] 1queue []for ch in s:if vis[ch] 0:while queue and queue[-1] > ch and cnt[queue[-1]]:vi…

《Advanced RAG》-03-使用 RAGAs + LlamaIndex 进行 RAG 评估

摘要 文章首先介绍了 RAG 评估的三个主要部分:输入查询、检索上下文和 LLM 生成的响应。 提到了 RAGAs 提出的 RAG 评估指标,包括 Faithfulness、Answer Relevance 和 Context Relevance,以及 RAGAs 网站提供的两个额外指标:Conte…

【面试题】分发糖果

这里写自定义目录标题 题目解题问题描述解题思路详细步骤初始化左到右扫描右到左扫描计算总糖果Python 代码示例 示例示例 1示例 2 复杂度分析 题目 仅供学习 解题 使用一种贪心算法的策略解决糖果分配问题。 问题描述 给定一个整数数组 ratings,表示每个孩子…

联邦学习研究综述【联邦学习】

文章目录 0 前言机器学习两大挑战: 1 什么是联邦学习?联邦学习的一次迭代过程如下:联邦学习技术具有以下几个特点: 2 联邦学习的算法原理目标函数本地目标函数联邦学习的迭代过程 3 联邦学习分类横向联邦学习纵向联邦学习联邦迁移…

功能实现——使用 RestTemplate 进行跨项目接口调用

目录 1.需求说明2.项目环境搭建3.代码实现3.1.使用 RestTemplate 进行调用3.1.1.项目 A3.1.2.项目 B 3.2.测试3.3.使用 JsonObject 来传递和接收 json 数据3.3.1.说明3.3.2.代码实现 3.4.其它说明3.4.1.restTemplate.exchange()3.4.2.restTemplate.postForObject()3.4.3.区别总…

8.4 字符串中等 443 String Compression 467 Unique Substrings in Wraparound String

443 String Compression 注意&#xff1a;这里是按照顺序压缩&#xff0c;不忽略顺序就不能用字母表计数再还原了。 如果char num 1 只需要压入char本身 num > 1 时还需要压入char的个数 按字符压入 class Solution { public:vector<char> Push(vector<char>&a…

Debug-019-git reflog的两种使用场景

前情&#xff1a;最近在开发项目中对版本管理有了新的理解&#xff0c;感觉在这方面有了新的收获。同时学习了一个新的git指令&#xff1a;git reflog 实际了解之后&#xff0c;发现这个指令不是很常用&#xff0c;但是对于特定的场景的话它还是非常比较方便 这里我列举两种我…

Nextjs——国际化那些事儿

背景&#xff1a; 某一天&#xff0c;产品经理跟我说&#xff0c;我们的产品需要搞国际化 国际化的需求说白了就是把项目中的文案翻译成不同的语言&#xff0c;用户想用啥语言来浏览网页就用啥语言&#xff0c;虽然说英语是通用语言&#xff0c;但国际化了嘛&#xff0c;产品才…

算法--初阶

1、tips 1.1、set求交集 {1,2,3} & {2,3} & {1,2} {2} 其实就是位运算&#xff0c; 只有set可以这样使用&#xff0c; list没有这种用法 {1,2,3} | {2,3, 4} | {1,2} {1, 2, 3, 4} 并集 1.2、*与** * 序列(列表、元组)解包&#xff0c;如果是字典&#xff0c;那…

第一个 Flask 项目

第一个 Flask 项目 安装环境创建项目启动程序访问项目参数说明Flask对象的初始化参数app.run()参数 应用程序配置参数使用 Flask 的 config.from_object() 方法使用 Flask 的 config.from_pyfile() 方法使用 Flask 的 config.from_envvar() 方法步骤 1: 设置环境变量步骤 2: 编…

【C++学习第19天】最小生成树(对应无向图)

一、最小生成树 二、代码 1、Prim算法 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 510, INF 0x3f3f3f3f;int n, m; int g[N][N]; int dist[N]; bool st[N];int prim() {memset(dist, 0x3f, sizeof di…

学习分享:解析电商 API 接入的技术重难点及解决方案

在当今电商业务迅速发展的时代&#xff0c;接入电商 API 已成为许多企业提升竞争力和拓展业务的重要手段。然而&#xff0c;在这个过程中&#xff0c;往往会遇到一系列的技术重难点。本文将深入解析这些问题&#xff0c;并提供相应的解决方案。 一、电商 API 接入的技术重难点 …

c++ 初始值设定项列表(initializer_list)

引例 我们在写c代码的时候&#xff0c;多多少少会遇到这样写的&#xff1a; 如果是这样写还好说&#xff1a; 第一个是因为编译器强制匹配参数。 其他都是因为在有对应构造函数的情况下支持的隐式类型转换。 而支持的构造函数是这个&#xff1a; 如果有不懂的可以开这一篇&a…

麦田物语第十八天

系列文章目录 麦田物语第十八天 文章目录 系列文章目录一、(Editor)制作 [SceneName] Attribute 特性二、场景切换淡入淡出和动态 UI 显示一、(Editor)制作 [SceneName] Attribute 特性 在本节课我们编写Unity的特性Attribute来更好的完善我们项目,具体是什么呢,就是当…

深入理解 ReLU 激活函数及其在深度学习中的应用【激活函数、Sigmoid、Tanh】

ReLU&#xff08;Rectified Linear Unit&#xff09;激活函数 ReLU&#xff08;Rectified Linear Unit&#xff09;激活函数是一种广泛应用于神经网络中的非线性激活函数。其公式如下&#xff1a; ReLU ( x ) max ⁡ ( 0 , x ) \text{ReLU}(x) \max(0, x) ReLU(x)max(0,x) 在…

docker部署elasticsearch和Kibana

部署elasticsearch 通过下面的Docker命令即可安装单机版本的elasticsearch&#xff1a; docker run -d \--name es \-e "ES_JAVA_OPTS-Xms512m -Xmx512m" \-e "discovery.typesingle-node" \-v es-data:/usr/share/elasticsearch/data \-v es-plugins:/u…

《LeetCode热题100》---<5.①普通数组篇五道>

本篇博客讲解LeetCode热题100道普通数组篇中的五道题 第一道&#xff1a;最大子数组和&#xff08;中等&#xff09; 第二道&#xff1a;合并区间&#xff08;中等&#xff09; 第一道&#xff1a;最大子数组和&#xff08;中等&#xff09; 法一&#xff1a;贪心算法 class So…