利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取

这篇具有很好参考价值的文章主要介绍了利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、 背景介绍

Etherscan 是 2015 年推出的一个以太坊区块探索和分析的分布式智能合同平台, 由于区块链中的交易信息等数据都是公开透明的 , 而 Etherscan 作为探索以太坊的窗口, 用户可以使用其查看自己的交易详情以及以太坊中的任何信息。

我们都有过这样的经历, 打开 taobao, 选了一件自己心仪已久的商品之后, 迫不及待的付了款, 看着卖家发了货之后, 心满意足的笑了笑。然而过了一天…两天…WTF (要文明, 其实是 where’s the food:)), 联系了卖家, 卖家告诉你 “亲, 我们已发货… …” 这时候, 有一个工具就是你的 “救命稻草” - 快递查询工具, 使用快递查询工具, 它会告诉你, 你的宝贝已经到了哪里, 距离你还有多少公里, 虽然对于快递的速度有些不爽, 但也足以安抚你焦躁的心灵。

其实在区块链世界中, 也有一个类似于上述 “快递查询工具” 的应用, 它就是 Etherscan, 网址是https://etherscan.io/
-----上文摘抄自知乎不得不备的工具 - Etherscan.io
在本项目中,打算在使用者给出一个Block的范围后,对该范围内的所有交易的信息做一个提取,并将最后提取的信息存入ether.json文件中。

二、信息提取规则

在最初始的Block网页中,先对每个交易的Txn_Hash和Method进行提取,再点击Txn_Hash进入详情页后,对详情页中的内容进行查找,假如有Transaction_Action这一项,则将该项爬取下来,否则直接返回即可。
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链
详情页:
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链

三、项目所用功能分析

该项目除了要使用最基本的网页爬取功能,还要实现对范围内的url的遍历、翻页功能、模拟打开详情页并将上一页的内容带入详情页中等一系列操作。

四、代码实现

爬虫的主体部分在spider文件夹的ether.py文件中:

import scrapy
import re

class EtherSpider(scrapy.Spider):
    handle_httpstatus_list = [404]
    name = 'ether'
    allowed_domains = ['etherscan.io']
    
    #start_urls = ['https://etherscan.io/txs?block=16538039&p=1']
    start_urls = 'https://etherscan.io/txs?block='


    def start_requests(self):
        #print()
        start = input('Please enter the Start and End Block values\n')
        end = input()
        #print(a)
        #print(b)
        for i in range(int (start),int (end)+1):

            #使用拼接以实现Block范围内数据的爬取
            url = self.start_urls + str(i) + '&p=1'


            #print(url)
            #continue

            #cookies为保障隐私不写出
            temp = ''
            cookies = {data.split('=')[0]: data.split('=')[-1]for data in temp.split(';')}  #将cookies转化为字典

            yield scrapy.Request(
                url=url,
                callback=self.parse,
                cookies=cookies
            )


    def parse(self, response):
        #获取当前页下的所有节点
        node_list = response.xpath('//*[@id="paywall_mask"]/table/tbody/tr')

        print(len(node_list))

        #遍历所有节点
        for node in node_list:
            temp = {}

            temp['Txn_Hash'] = node.xpath('./td[2]/span/a/text()').extract_first()

            temp['Method'] = node.xpath('./td[3]/span/text()').extract_first()

            #response.urljoin()用于拼接相对路径的url
            temp['link'] = response.urljoin(node.xpath('./td[2]/span/a/@href').extract_first())

            #print(temp)

            #构建详细页面请求
            yield scrapy.Request(
                url=temp['link'],
                callback=self.parse_detail,
                meta={'temp':temp}
            )

        #模拟翻页
        part_url = response.xpath('//*[@id="ContentPlaceHolder1_topPageDiv"]/nav/ul/li[4]/a/@href').extract_first()
        #print(part_url)
        #判断终止条件
        if part_url != None:
            next_url=response.urljoin(part_url)
            print(next_url)
            #构建请求对象并且返回给引擎
            yield scrapy.Request(
                url=next_url,
                callback=self.parse
                #dont_filter=True
            )



    def parse_detail(self,response):
        temp= response.meta['temp']

        # temp['Transaction Action'] = response.xpath('//*[@id="ContentPlaceHolder1_maintable"]/div[5]/div[2]/text()').extract_first().strip()
        #用于定位详情页中是否有Transaction_Action这个内容,以state的状态是否为None来判断
        state = response.xpath('//i[contains(@class, "fa-lightbulb-on") and contains(@class, "text-info")]/../../..//ul[@id="wrapperContent"]').extract_first()

        #if temp['Method'] == 'Approve':
        if state != None:
            #print('Yes-----------')
            #print(state)
            state = re.sub('\<.*?\>',' ',state)
            temp['Transaction_Action'] = re.sub(' +', ' ', state)
            #print(temp)
            #print('aaaa--------------')
            #temp['Transaction Action'] = BeautifulSoup(state,'html.parser')
            
        #print(temp)
        yield temp
        #print('111')

由于最后爬取的文件要存储在一个文件中,所以还要在管道(pipelines.py)文件中进行编辑。

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
import json

class Task1Pipeline:

    def __init__(self):
        self.file=open('ether.json',"w")



    def close_spider(self):
        self.file.close()

    
    def process_item(self, item, spider):
        # print('-----------------')
        # print(item)
        # print('-----------------')
        #将字典序列化
        json_data = json.dumps(item) + ',\n'

        #print(json_data)
        #print('0000000000000000000000000000')
        #将数据写入文件
        self.file.write(json_data)

        #默认使用完管道后需要将数据返回给引擎
        return item

五、代码运行

执行以下命令后:

C:\python\task1>scrapy crawl ether

按提示输入以下内容(为节省时间故只爬连续的两页):

Please enter the Start and End Block values
16538039
16538040

六、运行结果分析

在爬虫开始时,文件夹中会出现一个ether.json的文件,但在爬虫结束前,该文件还一直都只是空的,在爬虫结束后,我们可以发现此时爬虫内容如下:
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链
可以看到最后爬取到了309条信息,如何验证我们最后爬取到的内容是正确的呢?
我们可以先看Block为16538039和16538040中总共有多少笔交易:
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链
可以发现175+134=309,和我们最后爬取出来的数据数目一致。
接着,我们可以随机从爬取出的数据里挑一条出来验证一下:

{"Txn_Hash": "0x2a8ddede06368c884a5c2b5d86262ee66661ccd938ebfb759b65e212e6505740", "Method": "Borrow", "link": "https://etherscan.io/tx/0x2a8ddede06368c884a5c2b5d86262ee66661ccd938ebfb759b65e212e6505740", "Transaction_Action": " Borrow 6,000 USDC From Aave Protocol V2 "},

进入link,查看这笔交易的信息:
利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取,爬虫学习,scrapy,区块链
二者信息是一致的。
由以上两个过程基本可以确定我们本次爬虫爬取到的数据是正确的。

七、实验总结

在该实验过程中确实遇到了很多之前为遇到过的问题,如该网站有一定的反爬措施,最后通过修改setting.py文件中的USER_AGENT参数即在爬取时带上cookies参数可以解决。在爬取时还会预定因为自己程序爬取速度过快导致被网站直接认定为机器人后服务器直接熔断导致无法爬取到完整的数据,最后通过调整CONCURRENT_REQUESTS与DOWNLOAD_DELAY两个参数解决了被服务器熔断的问题。
虽然最后该爬虫可以基本完成实验要求,但其还有一个最致命的缺点----爬取时间太长了,在该样例中,只是进行爬取了两个Block内309条交易的信息,就总共花费了9分钟的时间,究其原因还是因为该程序的思路还是太过简单了,是一页一页进行爬取,爬完一页再进行翻页操作的,后续可以通过多页同时发起请求的方式进行爬取,以提高程序效率。文章来源地址https://www.toymoban.com/news/detail-660020.html

到了这里,关于利用scrapy框架对etherscan.io中给定Block范围内的交易信息的爬取的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 如何在 MATLAB 中生成指定范围内的随机数

    如何在 MATLAB 中生成指定范围内的随机数 在 MATLAB 中,我们可以使用内置函数来生成指定范围内的随机数。这些函数包括 rand 、 randi 和 randn ,它们分别用于生成在[0,1)范围内的均匀分布随机数、在指定范围内的整数随机数以及符合标准正态分布的随机数。 下面我将为你展示如

    2024年02月06日
    浏览(55)
  • LeetCode 2559. 统计范围内的元音字符串数:前缀和

    力扣题目链接:https://leetcode.cn/problems/count-vowel-strings-in-ranges/ 给你一个下标从 0 开始的字符串数组 words 以及一个二维整数数组 queries 。 每个查询 queries[i] = [l i , r i ] 会要求我们统计在 words 中下标在 l i 到 r i 范围内( 包含 这两个值)并且以元音开头和结尾的字符串的数目。

    2024年02月07日
    浏览(44)
  • ElasticSearch - 根据经纬度,简单搜索指定距离范围内的数据

    ES的地图检索方式 ES支持的地图检索方式有以下几种; geo_distance geo_bounding_box geo_polygon 1、 geo_distance :直线距离检索,如给定点A,要求返回地图上距离点A三千米的商家(点外卖场景) 2、查找索引内距离北京站(116.433733,39.908404)3000米内的点 geo_distance涉及的参数如下 location:确

    2024年02月14日
    浏览(44)
  • Python自动计算Excel数据指定范围内的区间最大值

      本文介绍基于 Python 语言,基于 Excel 表格文件内某一列的数据,计算这一列数据在每一个 指定数量的行 的范围内(例如每一个 4 行的范围内)的 区间最大值 的方法。   已知我们现有一个 .csv 格式的 Excel 表格文件,其中有一列数据,我们希望对其加以 区间最大值 的

    2024年02月15日
    浏览(37)
  • 2023-06-02 LeetCode每日一题(统计范围内的元音字符串数)

    点击跳转到题目位置 给你一个下标从 0 开始的字符串数组 words 以及一个二维整数数组 queries 。 每个查询 queries[i] = [li, ri] 会要求我们统计在 words 中下标在 li 到 ri 范围内( 包含 这两个值)并且以元音开头和结尾的字符串的数目。 返回一个整数数组,其中数组的第 i 个元素

    2024年02月07日
    浏览(51)
  • PTA 7-6 找完数:寻找任意范围内的完数及因子分解式

    通过编写程序,在给定范围内找出所有完数,并按照因子累加形式的分解式逐行输出。了解完数的定义及如何寻找完数。

    2024年02月06日
    浏览(120)
  • [SQL开发笔记]BETWEEN操作符:选取介于两个值之间的数据范围内的值

    一、功能描述: BETWEEN操作符:选取介于两个值之间的数据范围内的值。这些值可以是数值、文本或者日期。 二、 BETWEEN 操作符语法详解: BETWEEN操作符语法: 参数说明: 1.column1, column2, ...:要选择的字段名称,可以为多个字段。如果不指定字段名称,则会选择所有字段。

    2024年02月08日
    浏览(46)
  • C++将字符串中包含指定字符串范围内的字符串全部替换

    将指定字符串所在的范围之内的字符串全部替换为指定的字符串。如: 源字符串: 转换后的字符串: 或者转换为: 本文就是记录一种将上述字符串替换成功的方法。其中转换之后的第一个字符串,实际上是将原有字符串中 “$START$” 和 “$END$” 替换为 “” (空字符串);

    2024年02月07日
    浏览(57)
  • selenium 要点击的元素被其他元素遮挡 or 无法找到非可视范围内的元素

    selenium 无法找到非可视范围内的元素 org.openqa.selenium.StaleElementReferenceException: The element reference of is stale; either the element is no longer attached to the DOM, it is not in the current frame context, or the document has been refreshed selenium 要点击的元素被其他元素遮挡 org.openqa.selenium.ElementClickInterceptedExce

    2024年02月10日
    浏览(32)
  • python:使用geopandas和rasterio将矢量范围内的栅格值赋为0并重新输出

    需求:有一个点shp文件和一个栅格,想要构建shp中每个点的缓冲区,并且缓冲区范围内的栅格值重新赋为0并输出新的tif文件 解决方法:使用python中的geopandas和rasterio中的掩膜操作实现 代码如下: 如果已有的是面文件,想要将面文件范围内的栅格值重新赋值,可以直接读取

    2024年02月13日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包