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

  • 这一节我们将之前爬取到的景点数据进行解析,并且保存为excel,便于后续使用,本节包含

    (1) 景点数据解析

    (2)数据保存到excel

1 编写爬虫

这次继续改进第二节的爬虫,新建一个爬虫文件叫 spiders/qiongyou_3.py

因为这一节开始我们直接解析返回的response了,所以不需要保存html了。

编写一个自定义程序去解析页面的源码提取我们需要的信息

        while True:# 先爬取3页 (测试)if page_number > 3:break# 解析当前页面内容(如果需要解析,可以在这里添加解析逻辑)page_source = self.driver.page_sourcefor item in self.parse_page(page_source):yield item

parse_page方法这样写

# 解析页面def parse_page(self, page_source):response = scrapy.Selector(text=page_source)print(response)sights = response.xpath('//ul[@id="poiLists"]/li')print('sights=', sights)for sight in sights:item = TourItem()item['title'] = sight.xpath('.//h3[@class="title fontYaHei"]/a/text()').get().strip()item['title_en'] = (sight.xpath('.//h3[@class="title fontYaHei"]/a/span/text()').get() or '').strip()print(f"\033[92m{item['title']}\033[0m")print(f"\033[92m{item['title_en']}\033[0m")yield item

先打通流程,所以只提取2个字段,景点中文名和英文名

这边title_en这么写的原因是景点的外文名可能是不存在的,如果不加处理地提取会报错导致程序直接中断。

2 修改 items

修改items.py ,定义我们自己的数据结构

# 定义数据结构
class TourItem(scrapy.Item):title = scrapy.Field()title_en = scrapy.Field()

3 修改 Pipelines

利用pipelines 来对数据进行保存。

import pandas as pdclass TourPipeline:def __init__(self):self.data = []def process_item(self, item, spider):self.data.append(dict(item))return itemdef close_spider(self, spider):df = pd.DataFrame(self.data)# 使用pandas 保存东京景点 到excel文件df.to_excel('tokyo_sights.xlsx', index=False)spider.log('Saved data to tokyo_sights.xlsx')

需要安装pandas。

pip install pandas

还需要在settings.py 中打开配置。

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

4 执行代码

scrapy crawl qys3 

在测试的时候发现,第一次调的时候,通常驱动启动的会比较慢(这个原因我们下一期说),而后面调试就很快,发现数据可以保存到excel 。

5 完整qiongyou_3.py代码 & items.py 代码

后续继续解析其他字段,这边就直接贴出代码。

# qiongyou_3.py
import re
import scrapy
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
from selenium import webdriver
from selenium.webdriver.remote.remote_connection import LOGGER
import logging
import timefrom tutorial2.items import TourItemclass QiongyouSpider(scrapy.Spider):name = 'qys3'allowed_domains = ['qyer.com']start_urls = ['https://place.qyer.com/tokyo/sight/']def __init__(self, *args, **kwargs):super(QiongyouSpider, self).__init__(*args, **kwargs)options = webdriver.ChromeOptions()options.add_argument('--headless')LOGGER.setLevel(logging.WARNING)self.driver = webdriver.Chrome(options=options)  # 替换为 ChromeDriver 的实际路径def start_requests(self):for url in self.start_urls:yield scrapy.Request(url=url, callback=self.parse)def parse(self, response):# 定义对网站的操作(保存HTML)self.driver.get(response.url)# 等待页面加载WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//ul[@id="poiLists"]')))page_number = 1while True:# 先爬取3页 (测试)if page_number > 40:break# 解析当前页面内容(如果需要解析,可以在这里添加解析逻辑)page_source = self.driver.page_sourcefor item in self.parse_page(page_source):yield item# 查找并点击 "下一页" 按钮try:# javascriptnext_button = self.driver.find_element(By.XPATH, '//a[@title="下一页"]')self.driver.execute_script("arguments[0].click();", next_button)page_number += 1time.sleep(2)  # 等待页面加载WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//ul[@id="poiLists"]')))except Exception as e:self.log(f"No more pages or failed to load next page: {e}")breakself.driver.quit()# 解析页面def parse_page(self, page_source):response = scrapy.Selector(text=page_source)print(response)sights = response.xpath('//ul[@id="poiLists"]/li')print('sights=', sights)for sight in sights:item = TourItem()item['title'] = sight.xpath('.//h3[@class="title fontYaHei"]/a/text()').get().strip()item['title_en'] = (sight.xpath('.//h3[@class="title fontYaHei"]/a/span/text()').get() or '').strip()item['img'] = (sight.xpath('.//p[@class="pics"]/a/img/@src').get() or '').strip()item['score'] = (sight.xpath('.//div[@class="info"]/span[@class="grade"]/text()').get() or '').strip()comment = (sight.xpath('.//span[@class="dping"]/a/text()').get() or '').strip()item['comment_url'] = 'https:' + (sight.xpath('.//span[@class="dping"]/a/@href').get() or '').strip()item['rank_title'] = (sight.xpath('.//div[@class="info"]//span[@class="infoSide"]/text()').get() or '').strip()item['select_user'] = (sight.xpath('.//p[@class="user"]/a/img/@src').get() or '').strip()item['select_comment'] = (sight.xpath('.//div[@class="txt"]/text() | .//p[@class="txt"]/text()').get() or '').strip()rank = (sight.xpath('.//div[@class="info"]//em[@class="rank orange"]/text()').get() or '').strip()review_count_pattern = r'(\d+)人点评'review_count_match = re.search(review_count_pattern, comment)if review_count_match:item['comment'] = int(review_count_match.group(1))else:item['comment'] = 0rank_pattern = r'第(\d+)位'rank_match = re.search(rank_pattern, rank)if rank_match:item['rank'] = int(rank_match.group(1))else:item['rank'] = 0print(f"\033[92m{item['title']}\033[0m")print(f"\033[92m{item['title_en']}\033[0m")print(f"\033[92m{item['img']}\033[0m")print(f"\033[92m{item['score']}\033[0m")print(f"\033[92m{item['comment_url']}\033[0m")print(f"\033[92m{item['comment']}\033[0m")print(f"\033[92m{item['rank_title']}\033[0m")print(f"\033[92m{item['rank']}\033[0m")print(f"\033[92m{item['select_user']}\033[0m")print(f"\033[92m{item['select_comment']}\033[0m")yield item# items.pyimport scrapy# 定义数据结构
class TourItem(scrapy.Item):title = scrapy.Field()title_en = scrapy.Field()img = scrapy.Field()score = scrapy.Field()comment = scrapy.Field()comment_url = scrapy.Field()rank_title = scrapy.Field()rank = scrapy.Field()select_user = scrapy.Field()select_comment = scrapy.Field()

最后爬取到的excel 效果:
在这里插入图片描述

下一期我们就把数据存储到mysql中。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【Java基础】动态代理与代理模式哪些事儿

文章目录 代理静态代理动态代理基于接口的jdk动态的demo源码解析Proxy.newProxyInstancejdk 动态的生成的字节码 基于父类的cglib动态代理源码解析 代理设计模式应用场景 Spring AOP小结 代理 代理其实就是扩展目标对象的功能,比如普通人不具备超人能力&#xff0c…

青少年绘画大赛兰州站:童梦起航 致敬科学 续写降压0号之父强国梦

2024年7月21日,“鹤舞童梦致敬科学精神”青少年绘画大赛在兰州隆重启幕。 活动邀请了多位重量级嘉宾担任评委,包括中国美术家协会会员、甘肃省油画协会常务理事马爱兵,兰州交通大学天佑美术馆馆长王欣,以及国家一级美术师蔡晓斌。…

什么是护网?2024护网行动怎么参加?一文详解_护网具体是做啥的

前言 最近的全国护网可谓是正在火热的进行中,有很多网安小白以及准大一网安的同学在后台问我,到底什么是护网啊?怎么参加呢?有没有相关的学习资料呢?在下不才,连夜整理出来了这篇护网详解文章,希…

Linux笔记 --- 基础指令

1.了解命令行 快捷键打开终端:altctrlT 2.入门命令 1)cd 切换工作路径,使用时直接在后面写下当前目录下的下级目录即可跳转,也有特殊用法,在此列出 2)ls ls 列举当前目录下的内容常见用法有两种&#xff…

若依ruoyi+AI项目二次开发

//------------------------- //定义口味名称和口味列表静态数据 const dishFlavorListSelectref([ {name:"辣度",value:["不辣","微辣","中辣","重辣"]}, {name:"忌口",value:["不要葱","不要…

【PostgreSQL 16】专栏日常

本专栏从 3 个月前开始着手准备&#xff0c;利用周末及节假日的时间来整理。 ldczzDESKTOP-HVJOUVN MINGW64 ~/mypostgres (dev) $ git lg |tee * 7a7f468 - (HEAD -> dev, origin/main, origin/dev, main) 完成服务端编程的初步整理 (6 minutes ago) <Laven Liu> * …

freertos的学习cubemx版

HAL 库的freertos 1 实时 2 任务->线程 3 移植 CMSIS_V2 V1版本 NVIC配置全部是抢占优先级 第四组 抢占级别有 0-15 编码规则&#xff0c; 变量名 &#xff1a;类型前缀&#xff0c; c - char S - int16_t L - int32_t U - unsigned Uc - uint8_t Us - uint…

企业公户验证API如何使用JAVA、Python、PHP语言进行应用

在纷繁复杂的金融与商业领域&#xff0c;确保每笔交易的安全与合规是至关重要的。而企业公户验证API&#xff0c;正是这样一位默默守护的数字卫士&#xff0c;它通过智能化的手段&#xff0c;简化了企业对公账户验证流程&#xff0c;让繁琐的审核变得快捷且可靠。 什么是企业公…

圣杯依然闪耀 --基于短时RSI的均值回归策略跑出30%年化

圣杯依然闪耀 RSI 永远是我最爱的指标 – 因为潮汐和回归是这个蓝色星球的生命年轮&#xff0c;这样的轮回也存在于交易世界。而 RSI 就是刻画市场中的潮汐和回归的最好指标之一。 年初我介绍过 Connor’s RSI。这次我们将探索 Connors 提出的一个基于短时 RSI 的均值回归策略…

F1冠军版洗地机开售,云鲸能否成为“冠军”?

云鲸&#xff0c;本是一种由风云气象约束为鲸形状而成的大气生物&#xff0c;其遨游苍穹&#xff0c;不染尘埃。而当云鲸“降入尘世”&#xff0c;也代表着一种极简且洁净的品质生活方式。 作为一家专业的清洁机器人企业&#xff0c;以此为名的云鲸将科技清洁与美学设计融为一…

MySQL客户端命令一节将.sql文件导入MySQL

MySql客户端命令 直接输入SQL语句 使用MySQL客户端连接到服务器之后&#xff0c;可以发送SQL语句到服务器执行&#xff0c;并且以&#xff1b;和\g, \G作为结束不同的结束方式显示内容有所不同** TIPS: ;和\g结尾以表格的形式显示结果\G以行的形式显示结果 在连接到服务器之后…

【React】详解受控表单绑定

文章目录 一、受控组件的基本概念1. 什么是受控组件&#xff1f;2. 受控组件的优势3. 基本示例导入和初始化定义函数组件处理输入变化处理表单提交渲染表单导出组件 二、受控组件的进阶用法1. 多个输入框的处理使用多个状态变量使用一个对象管理状态 2. 处理选择框&#xff08;…

拉提查合创5步玩转git工具协作代码开发

1 工具使用场景 开发团队使用git版本管理工具&#xff0c;进行协作代码开发过程中&#xff0c;最常用的场景为&#xff1a; &#xff08;1&#xff09;拉取代码 将git远端仓库最新代码拉取到本地。 &#xff08;2&#xff09;提交代码 将本地新增修改的代码提交至git远端仓库中…

Django项目中报错:django.template.exceptions.TemplateDoesNotExist: index.html

访问127.0.0.1&#xff1a;8000访问出错 查看报错原因 到Django项目当中找到settings.py&#xff0c;找到TEMPLATES中的DIRS: 添加如下代码&#xff0c;并导入OS模块&#xff1a; "DIRS": [os.path.join(BASE_DIR,templates)] 再次访问IP地址&#xff1a;

Shell编程之正则表达式与文本三剑客

目录 一、正则表达式 1.引言--什么是正则表达式 1.1正则表达式的功能 2.基础正则表达式&#xff08;BRE&#xff09; 2.1特殊字符 2.2定位符 2.3非打印字符 3.扩展正则表达式(ERE) 4.元字符操作的案列 二、命令小工具 1.cut&#xff1a;列截取工具 2.sort排序 …

Footprint Analytics 助力 Core 区块链实现数据效率突破

Core 是一个基于比特币并兼容 EVM 的 Layer 1 区块链&#xff0c;正通过其创新解决方案引革新特币金融。作为首个引入非托管 BTC 质押协议及全球首个发行收益型 BTC ETP 产品的区块链&#xff0c;Core 站在了区块链技术的最前沿。通过利用超过 50% 的比特币挖矿哈希算力&#x…

SQL Server 设置端口号:详细步骤与注意事项

目录 一、了解SQL Server端口号的基础知识 1.1 默认端口号 1.2 静态端口与动态端口 二、使用SQL Server配置管理器设置端口号 2.1 打开SQL Server配置管理器 2.2 定位到SQL Server网络配置 2.3 修改TCP/IP属性 2.4 重启SQL Server服务 三、注意事项 3.1 防火墙设置 3…

《GPT-4o mini:开启开发与创新的新纪元》

在科技发展的快速进程中&#xff0c;OpenAI 推出的 GPT-4o mini 模型如同一阵春风&#xff0c;给开发者们带来了新的希望和机遇。它以其卓越的性能和极具吸引力的价格&#xff0c;成为了行业内热议的焦点。 当我首次听闻 GPT-4o mini 的消息时&#xff0c;内心充满了好奇与期待…

【Gin】Gin框架性能优化:精进应用效率与稳定性的对象池策略(上)

【Gin】Gin框架性能优化&#xff1a;精进应用效率与稳定性的对象池策略(上) 大家好 我是寸铁&#x1f44a; 【Gin】Gin框架性能优化&#xff1a;精进应用效率与稳定性的对象池策略(上)✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 本次文章分为上下两部分&#xff0c;上部…