数据采集与融合第三次作业

news/2024/11/8 11:54:22/文章来源:https://www.cnblogs.com/--xxxx-----/p/18534124
码云仓库地址 https://gitee.com/sun-jiahui22/crawl_project
作业1仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业3/实验3.1
作业2的仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业3/实验3.2
作业3的仓库地址 https://gitee.com/sun-jiahui22/crawl_project/tree/master/作业3/实验3.3
学号姓名 102202115 孙佳会

作业①

要求
指定一个网站,爬取这个网站中的所有的所有图片,例如:中国气象网(http://www.weather.com.cn)。使用scrapy框架分别实现单线程和多线程的方式爬取。

–务必控制总页数(学号尾数2位)、总下载的图片数量(尾数后3位)等限制爬取的措施。
输出信息:

将下载的Url信息在控制台输出,并将下载的图片存储在images子文件中,并给出截图。

爬取图片

🌱实现思路

爬虫 (weather.py):

WeatherSpider类通过分页链接递归抓取多个页面,每个页面上的所有图片链接被提取并保存到WeatherSpiderItem中。爬虫抓取的最大页面数和图片数由settings.py中的配置MAX_PAGES和MAX_IMAGES控制。

Item (items.py):

WeatherSpiderItem类定义爬虫抓取的数据结构

Pipeline (pipelines.py):

该管道负责管理图片的下载过程,包括发起请求、过滤掉下载失败的图片

配置 (settings.py):

爬虫的行为在settings.py中进行配置,例如:控制最大页面数(MAX_PAGES)。控制每个页面抓取的最大图片数(MAX_IMAGES)。配置图片下载的位置和存储格式等。

🎨主要代码

1.settings.py:

# 控制总页数
MAX_PAGES = 5  # 这里设置为5页,根据学号尾数进行调整
# 控制总下载的图片数量
MAX_IMAGES = 115  # 这里设置为115张IMAGES_STORE = 'images'  # 图片存储目录
ITEM_PIPELINES = {'weather_spider.pipelines.WeatherSpiderPipeline': 1,
}

2.pipelines.py:

class WeatherSpiderPipeline(ImagesPipeline):def get_media_requests(self, item, info):for url in item['image_urls']:yield scrapy.Request(url)def item_completed(self, results, item, info):# 过滤没有下载成功的图片if not item['images']:raise DropItem("Item contains no images")return item

3.items.py:

class WeatherSpiderItem(scrapy.Item):image_urls = scrapy.Field()images = scrapy.Field()

4.weather.py:

class WeatherSpider(scrapy.Spider):name = 'weather'allowed_domains = ['weather.com.cn']start_urls = ['http://www.weather.com.cn/']def parse(self, response):pages = response.css('div.page a::attr(href)').getall()for page in pages[:self.settings.getint('MAX_PAGES')]:yield response.follow(page, self.parse_page)def parse_page(self, response):image_urls = response.css('img::attr(src)').getall()item = WeatherSpiderItem()item['image_urls'] = image_urls[:self.settings.getint('MAX_IMAGES')]# 输出每个图片的下载URLfor url in item['image_urls']:self.logger.info(f'Downloading image from URL: {url}')yield item

运行结果:

终端输出:


images文件夹:

由于网站上图片总数并没有115张,所以只爬取了能爬取到的所有图片。

单线程爬取

scrapy默认多线程,如果需要单线程,在settings.py里进行设置:

# 下载延迟
DOWNLOAD_DELAY = 1  # 单线程下载速度# 单线程模式
CONCURRENT_REQUESTS = 1

爬取结果与多线程一样,不再展示。

心得体会

  • 这次开发Scrapy爬虫项目,我对数据抓取、处理和存储有了更加深入的理解,尤其是Scrapy框架的高效性和灵活性。
  • Scrapy框架为我们提供了清晰的结构,爬虫的各个部分(爬虫、Item、Pipeline等)相互配合,使得开发过程变得系统化。特别是在处理大规模数据抓取时,Scrapy能够自动化地管理请求、响应和数据存储,大大提高了效率。

作业②

要求
熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取股票相关信息。
候选网站
东方财富网:https://www.eastmoney.com/

输出信息
MySQL数据库存储和输出格式如下:
表头英文命名例如:序号id,股票代码:bStockNo……,由同学们自行定义设计

股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
301522 N上大 79.85 1060.61 72.97 595675 5031370784.78 582.56 102.00 61.92 61.92 6.88

爬取股票信息

🌱解析网页结构:

1.选择爬取“沪深京A股”板块


可以得到url为:https://quote.eastmoney.com/center/gridlist.html#hs_a_board

2.股票信息结构


根据此,设计XPATH爬取相应所需信息

3.翻页处理


根据此,设计翻页逻辑

🌱实现思路

1. Selenium 模拟浏览器爬取

  • 东方财富网的股票数据是通过 JavaScript 动态加载的,Scrapy 无法直接抓取。
  • 所以,使用 Selenium 来模拟浏览器,加载完整的页面内容,再用 Selenium 定位和提取动态加载的数据。这样可以确保数据在页面上完全加载后再进行解析。

2. MySQL 数据库准备

  • 在 MySQL 中创建数据库和表,数据库 stock_db,表 stock_data 。
  • 如果数据库中尚未存在 stock_data 表,创建该表以存储股票相关数据

3. 爬虫编写

初始化 Selenium

  • 在爬虫类的 __init__ 方法中,初始化 Selenium WebDriver,配置 ChromeOptions 为无头模式(headless)并设置 User-Agent。

解析网页

  • parse 方法中,使用 Selenium 加载东方财富网的目标 URL(例如:https://quote.eastmoney.com/center/gridlist.html#hs_a_board)。
  • 等待页面加载完成后,定位包含股票信息的表格。
  • 使用显式等待(如 WebDriverWaitexpected_conditions)确保数据完全加载,避免出现元素未加载导致定位失败的情况。

数据提取

  • 通过 Selenium 定位包含股票信息的行,逐行提取股票的各项数据,包括代码、名称、最新报价、涨跌额等。
  • 使用 Selenium 的 find_elements_by_xpath 方法来获取每一行的单元格数据,确保定位路径正确。
  • 将提取的数据存储到 StockItem 对象中,便于后续在 pipeline 中处理。

4. 数据存储

连接数据库

  • open_spider 方法中,建立与 MySQL 的连接。
  • close_spider 方法中,关闭数据库连接。

数据插入

  • process_item 方法中,将每条爬取到的数据插入到数据库表 stocks 中。
  • 检查字段格式,例如确保日期和浮点数的格式符合 MySQL 的要求。
  • 使用 try-except 处理插入时可能出现的异常,例如重复插入、格式不符等。

🎨主要代码:

  • 初始化爬虫并加载页面,使用 Selenium 的 driver.get() 方法加载东方财富网的目标页面。设置 max_pages 为最大页面数(5页),并初始化current_page为 1,表示从第一页开始爬取数据。
  • 使用显式等待(WebDriverWait)确保页面加载完成,并定位包含股票信息的表格行( 元素)。一旦找到该表格,将行数据存入 rows 列表。
    def parse(self, response):self.driver.get(response.url)max_pages = 5current_page = 1while current_page <= max_pages:# 等待页面加载必要的元素WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//table[@id="table_wrapper-table"]/tbody/tr')))rows = self.driver.find_elements(By.XPATH, '//table[@id="table_wrapper-table"]/tbody/tr')print(f"Processing page {current_page} with {len(rows)} rows")for row in rows:cells = row.find_elements(By.TAG_NAME, 'td')
  • 翻页操作,尝试点击“下一页”按钮。使用显式等待确保“下一页”按钮可点击,然后点击按钮并递增 current_page。等待页面刷新,以确保新数据加载完成。在页面刷新期间,使用 EC.staleness_of(rows[0]) 等待上一页的元素失效。如果无法找到“下一页”按钮,或点击出现异常,则终止循环。
# 检查是否有下一页并且尝试点击try:next_button = WebDriverWait(self.driver, 10).until(EC.element_to_be_clickable((By.XPATH, '//a[@class="next paginate_button"]')))next_button.click()current_page += 1# 等待页面刷新WebDriverWait(self.driver, 10).until(EC.staleness_of(rows[0]))except Exception as e:print(f"No more pages or unable to click next. Error: {e}")break
  • Scrapy 数据管道,用于将爬取的股票数据存储到 MySQL 数据库中
class StockPipeline:def open_spider(self, spider):# 连接 MySQL 数据库self.conn = mysql.connector.connect(host=spider.settings.get('MYSQL_HOST'),user=spider.settings.get('MYSQL_USER'),password=spider.settings.get('MYSQL_PASSWORD'),database=spider.settings.get('MYSQL_DATABASE'))self.cursor = self.conn.cursor()
  • StockItem 类用于存储爬取到的股票数据,并定义了与股票相关的多个字段。每个字段使用 scrapy.Field() 进行声明,以便 Scrapy 能够识别并处理这些字段。
class StockItem(scrapy.Item):id = scrapy.Field()bStockNo = scrapy.Field()      # 股票代码bStockName = scrapy.Field()    # 股票名称bLastPrice = scrapy.Field()    # 最新报价bChangeRate = scrapy.Field()   # 涨跌幅bChangeAmount = scrapy.Field() # 涨跌额bVolume = scrapy.Field()       # 成交量bAmplitude = scrapy.Field()    # 振幅bHigh = scrapy.Field()         # 最高价bLow = scrapy.Field()          # 最低价bOpen = scrapy.Field()         # 今开bPrevClose = scrapy.Field()    # 昨收

运行结果:


爬取到了所需股票信息。

心得体会

在这次项目中,我学习并掌握了如何在 Scrapy 项目中集成 Selenium 和 MySQL 数据库。

  • 动态页面处理的挑战

在现代网页开发中,许多内容是通过 JavaScript 动态加载的,传统的 Scrapy 抓取方式无法直接获取这些数据。通过将 Selenium 集成到 Scrapy 中,可以加载并解析动态内容,从而实现对更多复杂页面的抓取。这让我认识到,在数据爬取中灵活运用多种工具是非常重要的。

  • 数据存储的重要性

在实际项目中,数据的持久化存储是非常关键的一步。通过将数据存储在 MySQL 数据库中,可以方便地对抓取的数据进行查询和分析。建立合理的数据库结构和配置合适的 Item Pipeline,不仅提高了数据处理的效率,也使得数据的管理更加规范化。

  • 自动化数据抓取的应用前景

在处理金融数据等实时数据时,自动化数据抓取可以极大提高数据的时效性和更新频率。这种技能在市场分析、商业情报、风险管理等领域都有广泛的应用前景。通过本次实践,我对自动化数据抓取的价值有了更深的体会,并对未来相关应用充满了期待。

遇到的问题与解决思路

在项目过程中,遇到了一些常见问题:

  • Selenium 配置问题:需要正确配置 WebDriver 和设置等待条件,确保页面加载完成后再提取数据。
  • MySQL 存储问题:正确设计数据库结构,避免数据类型不匹配或字段空值导致的错误。
  • 数据提取结构复杂:通过浏览器的开发者工具确定表格的确切结构,利用 Selenium 的 Xpath 选择器准确定位需要的字段。为了简化代码和提升稳定性,可以将提取的数据字段逐个检查和验证,确保每一列的数据提取无误。

作业③

要求
熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取外汇网站数据。
候选网站
中国银行网:https://www.boc.cn/sourcedb/whpj/
输出信息

Currency TBP CBP TSP CSP Time
阿联酋迪拉姆 198.58 192.31 199.98 206.59 11:27:14

爬取中国银行外汇数据

🌱解析网页结构:

外汇信息

根据此,设计XPATH爬取信息方式。

🌱实现思路:

由于页面内容是动态加载的,我们采用了 Selenium 驱动的 WebDriver 来加载网页,以确保页面完全呈现后再抓取数据:

1.初始化 Selenium WebDriver

在爬虫的初始化部分配置 Selenium 的 Chrome WebDriver,这样在实际爬取过程中可以自动加载动态内容。

2. 数据抓取流程

  • 通过 Selenium 加载目标网页,并设置明确的等待条件,以确保页面内容加载完成,尤其是表格内容。
  • 使用 XPath 定位页面中的表格,并对表格的每一行进行数据提取。
  • 每行数据分别对应 ForexItem 中的一个字段,并将每个 ForexItem 实例传递到数据存储管道进行处理。

3. 数据存储管道

pipelines.py 文件中,通过 MySQL 数据库管道将数据持久化存储:

  • 数据库连接管理:在 open_spider 方法中建立数据库连接,并在初次启动时检查并创建数据表。这一步可以确保数据存储有条不紊地进行,且不会重复创建表格。

  • 数据插入与格式化:在 process_item 中,将每一条数据记录插入到 MySQL 数据表中,并根据特定格式处理数值类型(如价格、变化幅度等)。

  • 关闭数据库连接:在爬虫结束时关闭数据库连接,确保没有资源泄露。

4. 配置文件设置

settings.py 中,设置了关键的全局配置,包括启用 Selenium 中间件、MySQL 数据库连接参数等。Scrapy 项目配置的模块化使得在不同环境中更改配置变得简单,同时确保项目的可移植性。

🎨主要代码

  • parse 方法是 Scrapy 中用于处理响应数据的主要方法。这里使用显式等待 (WebDriverWait) 来确保页面上需要的数据元素(外汇牌价表格)已经加载完成。我们等待的条件是页面中的表格元素(通过 XPath 定位)能够被找到。成功加载页面后,我们使用 find_elements 获取所有包含数据的行,每一行表示一个货币的外汇信息。
 def parse(self, response):# 使用 Selenium 加载页面self.driver.get(response.url)try:# 显式等待,确保表格第一个单元格加载完成WebDriverWait(self.driver, 10).until(EC.presence_of_element_located((By.XPATH, '//table[@cellpadding="0" and @cellspacing="0" and @width="100%"]/tbody/tr/td')))print("Table loaded successfully.")except Exception as e:print("Error loading table:", e)self.driver.quit()return# 定位表格行并提取数据rows = self.driver.find_elements(By.XPATH,'//table[@cellpadding="0" and @cellspacing="0" and @width="100%"]/tbody/tr')print(f"Found {len(rows)} rows")for row in rows:cells = row.find_elements(By.TAG_NAME, 'td')
  • ForexPipeline 类用于处理从 Scrapy 爬虫获取的数据并将其存储到 MySQL 数据库中。该类定义了打开数据库连接、创建表格、插入数据,以及关闭数据库连接的过程。(只展示部分)
class ForexPipeline:def open_spider(self, spider):self.conn = mysql.connector.connect(host='localhost',user='root',password='123456',database='forex_data')self.cursor = self.conn.cursor()self.cursor.execute('''CREATE TABLE IF NOT EXISTS forex_data (id INT AUTO_INCREMENT PRIMARY KEY,Currency VARCHAR(255),TBP FLOAT,CBP FLOAT,TSP FLOAT,CSP FLOAT,Time TIME)''')self.conn.commit()
  • ForexItem 类定义了数据结构,用于存储和管理从 Scrapy 爬虫中提取的外汇信息。
class ForexItem(scrapy.Item):Currency = scrapy.Field()TBP = scrapy.Field()CBP = scrapy.Field()TSP = scrapy.Field()CSP = scrapy.Field()Time = scrapy.Field()

运行结果:

心得体会

  • 对scrapy框架更加熟悉,非常清晰高效。
  • 对Selenium模拟浏览器进行自动抓取、自动翻页等的操作理解更加深入

遇到的问题与解决思路

数据格式处理

  • 问题:一些数据带有符号(如百分号“%”)或其他特殊字符,直接插入 MySQL 时会出错。
  • 解决方法:在 process_item 中对数据进行清洗。例如,去除多余字符,将百分比转换为浮点数,并对空数据处理成 None,确保数据格式与数据库表结构匹配。

MySQL 数据库连接异常

  • 问题:在插入数据时出现了 MySQL 连接问题,比如“Access denied for user”或“数据库管道连接失败”。
  • 解决方法:确保数据库配置正确,包括用户名、密码和数据库名称。同时,确认 MySQL 服务已启动并允许远程访问。加入异常处理,避免程序因数据库错误而中断。

数据重复与插入错误

  • 问题:有时会出现数据重复或因为主键冲突导致的插入错误。
  • 解决方法:在数据库中增加数据唯一约束,或者在抓取过程中判断数据是否已经存在,避免重复插入。对于可能的插入错误,加入异常处理逻辑,确保数据管道稳定。

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

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

相关文章

【java编程】深入浅出JVM(四):类文件结构

原创 菜菜的后端私房菜Java文件编译成字节码文件后,通过类加载机制到Java虚拟机中,Java虚拟机能够执行所有符合要求的字节码,因此无论什么语言,只要能够编译成符合要求的字节码文件就能够被Java虚拟机执行. Java虚拟机和字节码是语言、平台无关性的基石. 本篇文章将深入浅出…

HyperWorks实体网格划分

实体网格剖分 在 HyperMesh 中,使用 Solid Map 功能进行实体网格剖分。该面板如下图所示:图 4-4 Solid Map 面板 通过 Solid Map Panel 进行实体网格剖分: • 通过主菜单栏选择 3D 页面 > solid map 。 • 通过下拉式菜单选择 Mesh > create > Solid Map。 Solid Ma…

VS 2022 不支持 .NET Framework 4.5 项目解决办法(Visual Studio 2022)

VS 2022 不支持 .NET Framework 4.5 项目解决办法(Visual Studio 2022) 概述 最近 C# 开发工具 Visual Studio 升级到了 2022,打开速度快了很多,开发体验也舒服很多。只是使用过程中遇到了一个比较尴尬的问题:默认Visual Studio 2022 不再支持安装 .NET Framework 4.5 组件…

新建流程隐藏指定流程(建模+api+ecode)

ecode代码 `// 功能总开关 let enable = true; let list=[]; $.ajax({ type:GET, url:/api/xiangxin/Multiple/HideProcess, success:function(res){ res.data.map((i)=>{ // console.log(lc :, i.lc); list.push(i.lc); }) } }) let pd; //判断是否是新建流程页面 ecodeSDK…

分布式事物传递 NetMQ测试

using NetMQ; using NetMQ.Sockets; using System; using System.Threading; namespace 消息传递库_NetMQ服务端 {internal class Program{public static void Main(){using (var publisher = new PublisherSocket()){// 绑定到一个端口,等待订阅者连接publisher.Bind("t…

Java实现身份证OCR识别API

近年来,随着业务量的不断增加,人工录入方式越来越难以满足高效办理业务的需求,而且越来越多的移动 APP涉及到个人身份证信息的实名认证,为了提高在移动终端上输入身份证信息的速度和准确性,一种可以识别并提取身份证上文字信息的技术接口应运而生,即身份证 OCR 识别 API …

调试优科R750 无线AP

最近项目上用到几个优科的R750设备,头一次整 一头雾水,还是英文太差了。其实官网上有许多手册,也有社区。 先是打了RUCKUS官网上的400电话,全是英文,没有办法找集成商要了销售的微信,他们介绍了一个技术,用微信给我传了一个升级固件(R750-200.9.10.4.233.bl7);后来我…

LeetCode 2544[交替数字和]

LeetCode 2544[交替数字和]题目 链接 LeetCode 2544[交替数字和] 详情实例提示题解 思路 依次求出各位数字,然后进行计算 循环找出各位数字:(循环体如下)将数字对10取余得到对应位数的数字,加入到容器 numVec数字除以10,得到新的数字,此数字是不包含已获取数字的位数 循…

Ubuntu系统下载

推荐LTS长期支持版本 下载地址 Ubuntu Releases至于下边这个网站,不推荐用,很可能下载到beta之类的版本 Index of /releases

人工智能入门

确定性计算,符号主义(早期人工智能) 不确定性计算:建模、机器学习(世界的随机性、不确定性和动态性 - 需要模式识别(学习)的能力,从数据中总结规律)智能即学习。人类的学习,是有类比思维的,得出方法论、哲学;机器的学习,只是在训练特征参数,没有灵性。机器学习常…

iOS-Tagent上新了,iOS17的wda的部署小技巧你get了吗

iOS17以上设备的wda安装小技巧来啦!快来get这个小技巧吧!感兴趣的同学可以戳推文详细阅读~此文章来源于项目官方公众号:“AirtestProject” 版权声明:允许转载,但转载必须保留原链接;请勿用作商业或者非法用途一、前言 之前有很多同学一直在问如何在iOS17的设备上安装wda…

antd Select下拉项数据过多,偶现下拉面板空白

问题 如下,偶现点击选择框,下拉面板空白(数据确定已返回)解决 查看github中的issues发现其他人也有同样的问题,大概是和 virtual list 有关 https://github.com/ant-design/ant-design/issues/26116修改代码如下: <Select...其他属性virtual={false} />