数据采集第三次实践作业

这个作业属于哪个课程 <首页 - 2024数据采集与融合技术实践 - 福州大学 - 班级博客 - 博客园 (cnblogs.com)>
这个作业要求在哪里 <作业3 - 作业 - 2024数据采集与融合技术实践 - 班级博客 - 博客园 (cnblogs.com)>
学号 <102202101>

一、作业内容

作业①

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

  • 代码如下

点击查看代码
class work1_Pipeline:
    count = 0
    desktopDir = str(pathlib.Path.home()).replace('\\','\\\\') + '\\Desktop'
    threads = []
    def open_spider(self,spider):
        picture_path=self.desktopDir+'\\images'
        if os.path.exists(picture_path):  # 判断文件夹是否存在
            for root, dirs, files in os.walk(picture_path, topdown=False):
                for name in files:
                    os.remove(os.path.join(root, name))  # 删除文件
                for name in dirs:
                    os.rmdir(os.path.join(root, name))  # 删除文件夹
            os.rmdir(picture_path)  # 删除文件夹
        os.mkdir(picture_path)  # 创建文件夹

    # # 单线程
    # def process_item(self, item, spider):
    #     url = item['img_url']
    #     print(url)
    #     img_data = urllib.request.urlopen(url=url).read()
    #     img_path = self.desktopDir + '\\images\\' + str(self.count)+'.jpg'
    #     with open(img_path, 'wb') as fp:
    #         fp.write(img_data)
    #     self.count = self.count + 1
    #     return item
    
    #多线程
    def process_item(self, item, spider):
        if isinstance(item, work1_Item):
            # 检查是否已下载了 10 张图片
            if self.count < 101:
                url = item['img_url']
                print(f"Downloading image {self.count + 1}: {url}")
                T = threading.Thread(target=self.download_img, args=(url,))
                T.setDaemon(True)  # 设置守护线程
                T.start()
                self.threads.append(T)
            else:
                print("Downloaded 101 images, stopping further downloads.")
        return item
  • 输出信息:


由于采用的是随机下一页的方法,故在一些界面可能出现报错,所以每次爬取的数量都不一定

  • Gitee文件夹链接:https://gitee.com/ma-xin1/data-acquisition/tree/master/weather_images

  • 心得体会:

    • 单线程爬取:如果需要爬取的页面较少,且目标网站响应速度较快,使用单线程爬取能够简化开发过程,并且性能差异不会很明显。
    • 多线程爬取:当需要抓取大量数据,或者目标网站的响应速度较慢时,多线程能够显著提高效率,减少总体爬取时间。

    作业②

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取股票相关信息。

  • 代码如下

点击查看代码
from typing import Iterable
import scrapy
from scrapy.http import Request
import re
import json
from Practical_work3.items import work2_Item

class Work2Spider(scrapy.Spider):
    name = 'work2'
    # allowed_domains = ['25.push2.eastmoney.com']

    start_urls = ['http://25.push2.eastmoney.com/api/qt/clist/get?cb=jQuery1124021313927342030325_1696658971596&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=f2,f3,f4,f5,f6,f7,f12,f14,f15,f16,f17,f18&_=1696658971636']
    def parse(self, response):
        data = response.body.decode()
        item = work2_Item()
        data = re.compile('"diff":\[(.*?)\]',re.S).findall(data)
        columns={'f2':'最新价','f3':'涨跌幅(%)','f4':'涨跌额','f5':'成交量','f6':'成交额','f7':'振幅(%)','f12':'代码','f14':'名称','f15':'最高',
        'f16':'最低','f17':'今开','f18':'昨收'}
        for one_data in re.compile('\{(.*?)\}',re.S).findall(data[0]):
            data_dic = json.loads('{' + one_data + '}')
            for k,v in data_dic.items():
                item[k] = v
            yield item



class work2_Pipeline:
    def open_spider(self, spider):
        try:
            self.db = pymysql.connect(host='127.0.0.1', user='root', passwd='Cjkmysql.', port=3306, charset='utf8',
                                      database='chenoojkk')
            self.cursor = self.db.cursor()
            self.cursor.execute('DROP TABLE IF EXISTS stock')
            sql = """CREATE TABLE stock(Latest_quotation Double,Chg Double,up_down_amount Double,turnover Double,transaction_volume Double,
            amplitude Double,id varchar(12) PRIMARY KEY,name varchar(32),highest Double, lowest Double,today Double,yesterday Double)"""
            self.cursor.execute(sql)
        except Exception as e:
            print(e)

    def process_item(self, item, spider):
        if isinstance(item, work2_Item):
            sql = """INSERT INTO stock VALUES (%f,%f,%f,%f,%f,%f,"%s","%s",%f,%f,%f,%f)""" % (
            item['f2'], item['f3'], item['f4'], item['f5'], item['f6'],
            item['f7'], item['f12'], item['f14'], item['f15'], item['f16'], item['f17'], item['f18'])
            self.cursor.execute(sql)
            self.db.commit()
        return item

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

  • 输出信息:

  • Gitee文件夹链接:https://gitee.com/ma-xin1/data-acquisition/tree/master/stock_scraper

  • 心得体会:

    • 在存储数据时,学会了如何将数据存入数据库,信息爬取的过程较为顺利,但是将爬取的信息存入数据库中遇到了一定的麻烦,在启用 item pipelines时遇到各种麻烦导致数据无法存入数据库,最后在同学的帮助下得以解决

    作业③

  • 要求:熟练掌握 scrapy 中 Item、Pipeline 数据的序列化输出方法;使用scrapy框架+Xpath+MySQL数据库存储技术路线爬取外汇网站数据。

  • 代码如下(使用scrapy框架+Xpath+MySQL数据库)

点击查看代码
import scrapy
from Practical_work3.items import work3_Item

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

    def parse(self, response):
        data = response.body.decode()
        selector=scrapy.Selector(text=data) 
        data_lists = selector.xpath('//table[@align="left"]/tr')
        for data_list in data_lists:
            datas = data_list.xpath('.//td')
            if datas != []:
                item = work3_Item()
                keys = ['name','price1','price2','price3','price4','price5','date']
                str_lists = datas.extract()
                for i in range(len(str_lists)-1):
                    item[keys[i]] = str_lists[i].strip('<td class="pjrq"></td>').strip()
                yield item



class work3_Pipeline:

    def open_spider(self,spider):
        try:
            self.db = pymysql.connect(host='127.0.0.1', user='root', passwd='Cjkmysql.', port=3306,charset='utf8',database='chenoojkk')
            self.cursor = self.db.cursor()
            self.cursor.execute('DROP TABLE IF EXISTS bank')
            sql = """CREATE TABLE bank(Currency varchar(32),p1 varchar(17),p2 varchar(17),p3 varchar(17),p4 varchar(17),p5 varchar(17),Time varchar(32))"""
            self.cursor.execute(sql)
        except Exception as e:
            print(e)

    def process_item(self, item, spider):
        if isinstance(item,work3_Item):
            sql = 'INSERT INTO bank VALUES ("%s","%s","%s","%s","%s","%s","%s")' % (item['name'],item['price1'],item['price2'],
                                                                                                    item['price3'],item['price4'],item['price5'],item['date'])
            self.cursor.execute(sql)
            self.db.commit()
        return item

    def close_spider(self,spider):
        self.cursor.close()
        self.db.close()
  • 输出信息:

  • Gitee文件夹链接:https://gitee.com/ma-xin1/data-acquisition/tree/master/forex_scraper

  • 心得体会:

    • Scrapy 框架 提供了一个完整的爬取和数据存储的解决方案,能够处理请求、解析、数据存储等问题,非常适合构建大规模爬虫。使用 MySQL 数据库 存储数据时,要注意表设计、字段类型、索引等问题,合理使用唯一约束和批量插入,提高性能。同时,在爬虫开发过程中,应该考虑到异常处理、反爬机制等问题,保证爬虫能够稳定高效运行。
posted @ 2024-11-08 20:42  Endorphins  阅读(16)  评论(0编辑  收藏  举报