数据采集与融合技术作业3

学号姓名 102202111 刘哲睿
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13285
这个作业的目标 用scrapy,Xpath和MySQL方法爬取各网站的数据信息
实验三仓库地址 https://gitee.com/qweasdzxc123-456/crawl_project/tree/master/数据采集实验3

作业①:

Gitee文件夹链接 https://gitee.com/qweasdzxc123-456/crawl_project/tree/master/数据采集实验3/图片/dangdang_scraper

要求:指定一个网站,爬取这个网站中的所有的所有图片,例如:中国气象网(http://www.weather.com.cn)。使用scrapy框架分别实现单线程和多线程的方式爬取。–务必控制总页数(学号尾数2位)、总下载的图片数量(尾数后3位)等限制爬取的措施。

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

  • 实验过程:

    1.使用 Scrapy 的命令行创建一个新的项目:
      scrapy startproject dangdang_scraper
      cd dangdang_scraper
    
    2.爬虫程序dangdang_images.py代码(总页数11页)、总下载的图片数量111张):
      class DangdangImagesSpider(scrapy.Spider):
      name = "dangdang_images"
      allowed_domains = ["search.dangdang.com", "img3m5.ddimg.cn", "img3m6.ddimg.cn", "img3m7.ddimg.cn", "img3m8.ddimg.cn"]
      start_urls = ["https://search.dangdang.com/?key=%CA%E9&act=input"]
      max_pages = 11
      max_images = 111
      image_count = 0
    
      def parse(self, response):
          # 修改选择器以获取正确的图片 URL
          images = response.xpath('//ul[@class="bigimg"]//img/@data-original').getall()
    
          # 控制图片数量
          for img_url in images:
              if self.image_count >= self.max_images:
                  return
              self.image_count += 1
              
              # 检查 URL 是否以 // 开头,添加协议
              if img_url.startswith('//'):
                  img_url = 'http:' + img_url  # 或 'https:',根据需要选择
              
              print(f"Scraping image URL: {img_url}")  # Debug print
              item = DangdangScraperItem()
              item['image_urls'] = [img_url]
              yield item
    
    3.items.py代码:
    import scrapy
    class DangdangScraperItem(scrapy.Item):
      # 定义你想要抓取的字段
      image_urls = scrapy.Field()  # 存储图片的 URL
      images = scrapy.Field()       # 存储下载后的图片信息
    
    
    4.settings.py代码:
    # 下载延迟(根据网站设置)
    DOWNLOAD_DELAY = 1.5
    # 图片存储路径
    IMAGES_STORE = r'C:\Users\刘哲睿\Desktop\Typora\数据采集实验3\图片\dangdang_scraper\images'
    # 启用 ImagesPipeline
    ITEM_PIPELINES = {
        'scrapy.pipelines.images.ImagesPipeline': 1,
    }
    FEED_EXPORT_ENCODING = "utf-8"
    SPIDER_MIDDLEWARES = {
        'scrapy.spidermiddlewares.offsite.OffsiteMiddleware': None,
    }
    DOWNLOADER_MIDDLEWARES = {
        'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
    }
    ITEM_PIPELINES = {
        'dangdang_scraper.pipelines.DangdangImagesPipeline': 1,
    }
    OFFSITE_ENABLED = False
    # 单线程
    CONCURRENT_REQUESTS = 1
    RETRY_ENABLED = True
    RETRY_TIMES = 3  # 重试次数
    
    若是要多线程爬取,则将线程数量改为16:
    CONCURRENT_REQUESTS = 16
    
    5.配置图片管道pipelines.py代码:
    from scrapy.pipelines.images import ImagesPipeline
    from scrapy.http import Request
    
    class DangdangImagesPipeline(ImagesPipeline):
        def get_media_requests(self, item, info):
            for image_url in item.get('image_urls', []):
                yield Request(image_url)
    
        def item_completed(self, results, item, info):
            item['images'] = [x['path'] for ok, x in results if ok]
            return item
    
    6.在终端输入运行命令:
    scrapy crawl dangdang_scraper
    

输出图片(111张):

  • 心得体会:

    通过本次针对当当网图片爬取的实验,我对Scrapy框架有了更深刻的认识,尤其是其在定向图片爬取方面的应用。Scrapy的ImagesPipeline极大地简化了图片下载和存储的工作,使爬虫编写变得轻松。以往处理图片相关任务时,需操心诸多细节,如今借助它,我们只需专注于提取图片链接这一核心逻辑,无需过多关注底层操作,提高了开发效率,降低了出错概率,让开发过程更顺畅。
    在实现单线程和多线程爬取过程中,我体会到多线程对提升爬取效率的重要性。调整CONCURRENT_REQUESTS等配置,可显著提升爬虫并发性能,加快图片下载速度。但同时要注意对目标网站的影响,避免因过度请求导致服务器压力过大。我们需在高效与友好之间找到平衡。
    总体而言,本次实验让我更熟悉Scrapy框架的使用,以及如何高效、规范地实现网页信息爬取,对我今后学习和实践帮助很大。

作业②

Gitee文件夹链接 https://gitee.com/qweasdzxc123-456/crawl_project/tree/master/数据采集实验3/股票/stock_scraper

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

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

  • 实验过程:

    1.使用 Scrapy 的命令行创建一个新的项目:
      scrapy startproject stock_scraper
      cd stock_scraper
    
    2.爬虫程序stock_spider.py代码:
     class StockSpider(scrapy.Spider):
      name = 'stock'
      start_urls = ['https://21.push2.eastmoney.com/api/qt/clist/get?cb=jQuery112401677766641902747_1730445460944&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&dect=1&wbp2u=|0|0|0|web&fid=f3&fs=b:DLMK0144&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f19,f20,f21,f23,f24,f25,f26,f22,f33,f11,f62,f128,f136,f115,f152&_=1730445460948']
    
      def start_requests(self):
          headers = {
              'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
          }
          for url in self.start_urls:
              yield scrapy.Request(url, headers=headers, callback=self.parse)
      def parse(self, response):
          text = response.text
          json_text = text[text.find('(') + 1:text.rfind(')')]
          json_data = json.loads(json_text)
          stocks = json_data.get('data', {}).get('diff', [])
    
          for stock in stocks:
              item = StockItem()
              item['bStockNo'] = stock.get('f12')  # 股票代码
              item['stockName'] = stock.get('f14')  # 股票名称
              item['latestPrice'] = stock.get('f2')  # 最新报价
              item['changeRate'] = stock.get('f3')  # 涨跌幅
              item['changeAmount'] = stock.get('f4')  # 涨跌额
              item['volume'] = stock.get('f5')  # 成交量
              item['amplitude'] = stock.get('f7')  # 振幅
              item['high'] = stock.get('f15')  # 最高
              item['low'] = stock.get('f16')  # 最低
              item['openPrice'] = stock.get('f17')  # 今开
              item['closePrice'] = stock.get('f18')  # 昨收
              yield item
    
    3.items.py代码:
    import scrapy
    
    class StockItem(scrapy.Item):
      id = scrapy.Field()  # 序号
      bStockNo = scrapy.Field()  # 股票代码
      stockName = scrapy.Field()  # 股票名称
      latestPrice = scrapy.Field()  # 最新报价
      changeRate = scrapy.Field()  # 涨跌幅
      changeAmount = scrapy.Field()  # 涨跌额
      volume = scrapy.Field()  # 成交量
      amplitude = scrapy.Field()  # 振幅
      high = scrapy.Field()  # 最高
      low = scrapy.Field()  # 最低
      openPrice = scrapy.Field()  # 今开
      closePrice = scrapy.Field()  # 昨收
    
    
    4.settings.py代码:
    BOT_NAME = "stock_scraper"
    
    SPIDER_MODULES = ["stock_scraper.spiders"]
    NEWSPIDER_MODULE = "stock_scraper.spiders"
    
    ROBOTSTXT_OBEY = False
    
    ITEM_PIPELINES = {
        "stock_scraper.pipelines.StockScraperPipeline": 300,
    }
    
    REQUEST_FINGERPRINTER_IMPLEMENTATION = "2.7"
    TWISTED_REACTOR = "twisted.internet.asyncioreactor.AsyncioSelectorReactor"
    FEED_EXPORT_ENCODING = "utf-8"
    
    ITEM_PIPELINES = {
        'stock_scraper.pipelines.StockScraperPipeline': 300,
    }
    USER_AGENT ='Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0'
    
    
    5.配置图片管道pipelines.py代码:
    class StockScraperPipeline:
      def open_spider(self, spider):
          self.connection = mysql.connector.connect(
              host='localhost',
              user='root',
              password='123456',
              database='hh'
          )
          self.cursor = self.connection.cursor()
    
      def close_spider(self, spider):
          self.connection.commit()
          self.cursor.close()
          self.connection.close()
    
      def process_item(self, item, spider):
          sql = """INSERT INTO stocks (bStockNo, stockName, latestPrice, changeRate, changeAmount, volume, amplitude, high, low, openPrice, closePrice) 
                   VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"""
          self.cursor.execute(sql, (
              item['bStockNo'], item['stockName'], item['latestPrice'],
              item['changeRate'], item['changeAmount'], item['volume'],
              item['amplitude'], item['high'], item['low'],
              item['openPrice'], item['closePrice']
          ))
          return item
    
    6.在终端输入运行命令:
    scrapy crawl stock
    

输出结果(sql库表格):

  • 心得体会:

    通过此次股票信息爬取及存储作业,我对 Scrapy 框架数据流处理机制,尤其是 Item 和 Pipeline 的协同工作有了深入认识。Item 定义数据结构,Pipeline 负责数据清洗、处理与存储,提升了程序模块化程度,便于维护和扩展。将股票信息存至 MySQL 数据库让我在数据库操作上进步显著,包括创建库表、规划字段等,确保了数据完整性和一致性,还熟练掌握了 Python 与 MySQL 交互技巧。
    作业中遇到网站反爬虫机制和数据格式不一致等问题,我通过调整爬取策略、增加数据验证与清洗步骤成功解决,加深了对爬虫实际应用技巧的理解,提升了解决问题能力,在技术层面和问题处理能力上都有收获,为后续探索积累了经验

作业③:

Gitee文件夹链接 https://gitee.com/qweasdzxc123-456/crawl_project/tree/master/数据采集实验3/外汇/forex_scraper

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

输出信息:(MySQL数据库存储和数据格式)

  • 实验过程:

    1.使用 Scrapy 的命令行创建一个新的项目:
      scrapy startproject forex_scraper
      cd forex_scraper
    
    2.爬虫程序boc.py代码:
      class BOCSpider(scrapy.Spider):
      name = 'boc'
      allowed_domains = ['boc.cn']
      start_urls = ['https://www.boc.cn/sourcedb/whpj/']
    
      def parse(self, response):
          rows = response.xpath('//tr[td]')
          for row in rows:
              item = ForexItem()
              item['currency'] = row.xpath('td[1]/text()').get()
              item['tbp'] = row.xpath('td[2]/text()').get()
              item['cbp'] = row.xpath('td[3]/text()').get()
              item['tsp'] = row.xpath('td[4]/text()').get()
              item['csp'] = row.xpath('td[5]/text()').get()
              item['time'] = row.xpath('td[7]/text()').get()
              yield item
    
    3.items.py代码:
    import scrapy
    
    class ForexItem(scrapy.Item):
        currency = scrapy.Field()
        tbp = scrapy.Field()  # 现汇买入价
        cbp = scrapy.Field()  # 现钞买入价
        tsp = scrapy.Field()  # 现汇卖出价
        csp = scrapy.Field()  # 现钞卖出价
        time = scrapy.Field()  # 发布时间
    
    4.settings.py代码:
    ITEM_PIPELINES = {
      "forex_scraper.pipelines.ForexPipeline": 300,
    

}

5.配置图片管道pipelines.py代码:
```python
import mysql.connector

class ForexPipeline:
  def open_spider(self, spider):
      self.connection = mysql.connector.connect(
          host='localhost',
          user='root',     # 替换为你的数据库用户名
          password='123456',  # 替换为你的数据库密码
          database='hh'       # 替换为你的数据库名
      )
      self.cursor = self.connection.cursor()
      self.cursor.execute('''CREATE TABLE IF NOT EXISTS forex (
          id INT AUTO_INCREMENT PRIMARY KEY,
          currency VARCHAR(255),
          tbp DECIMAL(10, 2),
          cbp DECIMAL(10, 2),
          tsp DECIMAL(10, 2),
          csp DECIMAL(10, 2),
          time VARCHAR(255)
      )''')
  
  def close_spider(self, spider):
      self.connection.commit()
      self.cursor.close()
      self.connection.close()

  def process_item(self, item, spider):
      self.cursor.execute('''
          INSERT INTO forex (currency, tbp, cbp, tsp, csp, time)
          VALUES (%s, %s, %s, %s, %s, %s)
      ''', (item['currency'], item['tbp'], item['cbp'], item['tsp'], item['csp'], item['time']))
      return item

6.在终端输入运行命令:

scrapy crawl boc

输出结果(sql库表格):

  • 心得体会:

    通过本次作业,我深入理解了 Scrapy 框架中 Item 和 Pipeline 的作用与实现。Item 定义数据结构,Pipeline 处理并存储数据(如存到 MySQL 数据库)。结合 XPath 提取数据,经 Pipeline 处理后存储。
    项目中综合运用 Scrapy、XPath 和 MySQL,包括用 Scrapy 爬虫和 XPath 从中国银行网外汇汇率页面抓数据,在 Pipeline 中处理,再用 PyMySQL 存到数据库。但在设计数据库表结构时,需要考虑到数据之间的关系和查询效率
    该作业巩固了我的相关技术知识,提升了我的技术能力和问题解决能力,积累了项目经验。
posted @ 2024-11-01 16:19  Con1427  阅读(9)  评论(0编辑  收藏  举报