数据采集与融合技术实践作业三

发布时间 2023-10-28 09:51:34作者: SPQ

第三次作业

Gitee链接

作业①:

要求:

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

输出信息:

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

Weather_Spider.py的代码如下:
import scrapy

class Weather_Spider(scrapy.Spider):
    name = 'Weather_Spider'
    allowed_domains = ['weather.com.cn']
    start_urls = ['http://www.weather.com.cn/']

    def parse(self, response):
        # 提取图片URL
        img_urls = response.css('img::attr(src)').extract()
        for img_url in img_urls:
            if img_url:  # 检查URL是否为空
                img_url = response.urljoin(img_url)  # 转换为绝对URL
                print(f"Downloading Image: {img_url}")  # 输出URL信息
                yield {'image_urls': [img_url]}  # 生成item
在setting.py中添加代码如下,用于确定网页图片的下载路径:
ITEM_PIPELINES = {
   'scrapy.pipelines.images.ImagesPipeline': 1,
}
IMAGES_STORE = r'C:\Users\佘培强\Desktop\数据融合与采集技术作业\images1'
在setting.py中添加CONCURRENT_REQUESTS的值可以实现多线程:
CONCURRENT_REQUESTS = 16

运行代码打印出图片的url:

在指定的文件夹中部分图片结果如下:

心得体会:

本来不知道多线程相较于单线程而言要怎么处理,经过查阅资料后发现scrapy爬取数据设置多线程只要在setting.py中进行相应的配置即可完成,除外本题依旧是如之前一样先找到网页中图片的url,然后将其爬取出。

作业②:

要求:

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

输出信息:MySQL数据库存储和输出格式如下:

表头英文命名例如:序号id,股票代码:bStockNo……
image

stock_spider.py的代码如下:
import scrapy
import json
from job1.items import Job1Item

class stock_spider(scrapy.Spider):
    name = 'stock_spider'
    start_urls = [
        'http://54.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124024635353550527928_1697698971058&pn=1&pz=20&po=1&np=1&ut=bd1d9ddb04089700cf9c27f6f7426281&fltt=2&invt=2&wbp2u=|0|0|0|web&fid=f3&fs=m:0+t:6,m:0+t:80,m:1+t:2,m:1+t:23,m:0+t:81+s:2048&fields=f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f12,f13,f14,f15,f16,f17,f18,f20,f21,f23,f24,f25,f22,f11,f62,f128,f136,f115,f152&_=1697698971059'
    ]

    def parse(self, response):
        jsonp = response.text
        json_text = jsonp[jsonp.find('(') + 1: jsonp.rfind(')')]
        json_data = json.loads(json_text)
        for stock_info in json_data['data']['diff']:
            item = Job1Item()
            item['股票代码'] = stock_info['f12']
            item['股票名称'] = stock_info['f14']
            item['最新价'] = stock_info['f2']
            item['涨跌幅'] = stock_info['f3']
            item['涨跌额'] = stock_info['f4']
            item['成交量'] = stock_info['f5']
            item['成交额'] = stock_info['f6']
            item['振幅'] = stock_info['f7']
            item['最高'] = stock_info['f15']
            item['最低'] = stock_info['f16']
            item['今开'] = stock_info['f17']
            yield item

items.py的代码如下:
import scrapy


class Job1Item(scrapy.Item):
    股票代码 = scrapy.Field()
    股票名称 = scrapy.Field()
    最新价 = scrapy.Field()
    涨跌幅 = scrapy.Field()
    涨跌额 = scrapy.Field()
    成交量 = scrapy.Field()
    成交额 = scrapy.Field()
    振幅 = scrapy.Field()
    最高 = scrapy.Field()
    最低 = scrapy.Field()
    今开 = scrapy.Field()


Pipelines.py的代码如下(创建并且连接数据库,将爬取得到的数据传入到数据库中):
import pymysql

class MySQLPipeline:

    def open_spider(self, spider):
        self.conn = pymysql.connect(host='localhost', user='root', password='123456', charset='utf8')
        self.cursor = self.conn.cursor()

        # 创建数据库
        self.cursor.execute("CREATE DATABASE IF NOT EXISTS stock_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;")
        self.conn.commit()

        # 选择数据库
        self.cursor.execute("USE stock_db")

        # 创建表格
        self.cursor.execute("""
        CREATE TABLE IF NOT EXISTS stocks (
            股票代码 VARCHAR(10),
            股票名称 VARCHAR(50),
            最新价 DECIMAL(10, 2),
            涨跌幅 DECIMAL(5, 2),
            涨跌额 DECIMAL(10, 2),
            成交量 BIGINT,
            成交额 BIGINT,
            振幅 DECIMAL(5, 2),
            最高 DECIMAL(10, 2),
            最低 DECIMAL(10, 2),
            今开 DECIMAL(10, 2)
        ) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
        """)
        self.conn.commit()

    def close_spider(self, spider):
        self.conn.commit()
        self.conn.close()

    def process_item(self, item, spider):
        sql = 'INSERT INTO stocks (股票代码, 股票名称, 最新价, 涨跌幅, 涨跌额, 成交量, 成交额, 振幅, 最高, 最低, 今开) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'
        values = (item['股票代码'], item['股票名称'], item['最新价'], item['涨跌幅'], item['涨跌额'], item['成交量'], item['成交额'], item['振幅'], item['最高'], item['最低'], item['今开'])
        self.cursor.execute(sql, values)
        self.conn.commit()
        return item

存储在数据库中的数据(采用Navicate可视化并且查看):

心得体会:

这题依旧和之前一样使用json包来处理爬取出数据,不一样的是这题采用了scrapy的方法来爬取出数据,相似的题目采取不同的做法使我对于scrapy相应的知识有了更深的体会,scrapy更需要注重各方面的配置,因此在使用scrapy时必须要检查好各项配置再执行

作业③:

要求:

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

输出信息:

image

bank_spider.py的代码如下所示:
import scrapy
from job2.items import Job2Item

class bank_spider(scrapy.Spider):
    name = 'bank_spider'
    start_urls = ['https://www.boc.cn/sourcedb/whpj/']

    def parse(self, response):
        rows = response.xpath('//table[@align="left"]/tr')
        count=1
        for row in rows[1:]:
            item = Job2Item()
            item['count']=count
            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()
            count+=1
            print(item)
            yield item

items.py的代码如下所示:
import scrapy


class Job2Item(scrapy.Item):
        count = scrapy.Field()
        currency = scrapy.Field()
        tbp = scrapy.Field()
        cbp = scrapy.Field()
        tsp = scrapy.Field()
        csp = scrapy.Field()
        time = scrapy.Field()

Pipelines.py的代码如下所示(创建并且连接数据库,并将爬取的数据传入到数据库中):

class Job2Pipeline(object):

    def __init__(self):
        self.conn = pymysql.connect(
            host='localhost',
            db='currencydb',
            user='root',
            password='123456',
            port=3306
        )
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):
        # 将Item数据插入到MySQL数据库
        insert_sql = """
              INSERT INTO currency_data (id, currency, tbp, cbp, tsp, csp, time)
              VALUES (%s, %s, %s, %s, %s, %s, %s)
          """
        values = (
            item['count'],
            item['currency'],
            item['tbp'],
            item['cbp'],
            item['tsp'],
            item['csp'],
            item['time']
        )
        try:
            self.cursor.execute(insert_sql, values)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            raise e

    def close_spider(self, spider):
        self.cursor.close()
        self.conn.close()


存储在数据库中的数据(采用Navicate可视化并且查看):

心得体会:

本题刚开始数据库中一直解析不了currency这一列的数据,无法将这一列的数据传入,后来在数据库中设置新的编码:utf8mb4,就可以成功解析出来结果