區塊鏈數據爬蟲實戰:使用 Python 爬取交易清單資料!

前言

今天主要分享如何利用爬蟲爬取區塊鏈瀏覽器上的交易列表數據。

原因

dune上沒有bsc鏈上的轉賬明細數據表。Footprint Analytics上現有的bsc_transactions表transfer_type粒度不夠。

環境

python 3.7

數據存儲:mysql 5.7

緩存:redis 6.2.6

開發工具:pycharm

思路

(1)所有協議、合約、swap地址轉賬信息全爬不太實際,對存儲要求比較高。所以針對需要分析的協議,專門去爬取對應智能合約轉賬是個不錯的選擇。

(2)區塊鏈瀏覽器肯定是有反爬機制的。所以在代理選擇上,要選擇國外的代理。國內的代理都訪問不到,具體原因你懂的。本文中不涉及代理部分,因為國外的代理廠家之前沒有了解過。不過即使是上代理,對代碼層面改動也比較小

(3)采用了urllib同步請求 + 范圍內隨機時長程序休眠。減少了被風控的概率。但是也降低了爬蟲的效率。

后面再研究用scrapy或異步請求 [1]

[1] 同步:請求發送后,需要接受到返回的消息后,才進行下一次發送。異步:不需要等接收到返回的消息。

實現

找到需要爬取合約的具體地址:

第一頁

http://bscscan.com/txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8

第二頁

https://bscscan.com/txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8&p=2

第三頁

https://bscscan.com/txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8&p=3

….

可以知道 p = ?就代表頁數。

然后F12 點擊“網絡”,刷新界面,查看網絡請求信息。

主要查看,網頁上顯示的數據,是哪個文件響應的。以什麼方式響應的,請求方法是什麼

python爬取區塊鏈瀏覽器上的交易列表數據

python爬取區塊鏈瀏覽器上的交易列表數據

如何驗證呢,就是找一個txn_hash在響應的數據里面按ctrl + f去搜索,搜索到了說明肯定是這個文件返回的。

python爬取區塊鏈瀏覽器上的交易列表數據

查看響應的數據,是html的格式。在python里面,處理html數據,個人常用的是xpath(當然,如果更擅長BeautifulSoup也可以)

在python里面安裝相關的依賴

pip install lxml ‐i https://pypi.douban.com/simple

同時在瀏覽器上安裝xpath插件,它能更好的幫助我們獲到網頁中元素的位置

XPath Helper – Chrome 網上應用店 (google.com)

然后就可以通過插件去定位了,返回的結果是list

**注:**瀏覽器看到的網頁都是瀏覽器幫我們渲染好的。存在在瀏覽器中能定位到數據,但是代碼中取不到值的情況,這時候可以通過鼠標右鍵-查看網頁源碼,然后搜索實現

python爬取區塊鏈瀏覽器上的交易列表數據

python爬取區塊鏈瀏覽器上的交易列表數據

# 請求和xpath定位具體實現代碼: def start_spider(page_number):     url_base = 'http://bscscan.com /txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8&'     # 請求頭     headers = {         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.159 Safari/537.36',         'referer': 'https://bscscan.com/txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8'     }     # 需要傳入的參數     data = {         'p': page_number     }     # 將參數轉為Unicode編碼格式     unicode_data = urllib.parse.urlencode(data)     # 拼接網址     # http://bscscan.com/txs?a=0xbd3bd95529e0784ad973fd14928eedf3678cfad8     url = url_base + unicode_data     # 自定義request對象     request = urllib.request.Request(url=url, headers=headers)     # 模擬瀏覽器發送請求     response = urllib.request.urlopen(request)     # 將返回的數據利用lxml轉為     tree = etree.HTML(response.read().decode('utf‐8'))     # //div[@id='paywall_mask']//tbody//td//span/a[@class='myFnExpandBox_searchVal']/text()     txn_hash_list = tree.xpath(https://div[@id='paywall_mask']//tbody//td//span/a[@class='myFnExpandBox_searchVal']/text())     # //div[@id='paywall_mask']//tbody//td//span[@class='u-label u-label--xs u-label--info rounded text-dark text-center']/text()     method_list = tree.xpath(         https://div[@id='paywall_mask']//tbody//td//span[@class='u-label u-label--xs u-label--info rounded text-dark text-center']/text())     # //div[@id='paywall_mask']//tbody//td[@class='d-none d-sm-table-cell']//text()     block_list = tree.xpath(https://div[@id='paywall_mask']//tbody//td[@class='d-none d-sm-table-cell']//text())     # //div[@id='paywall_mask']//tbody//td[@class='showAge ']/span/@title     age_list = tree.xpath(https://div[@id='paywall_mask']//tbody//td[@class='showAge ']/span/@title)     # //div[@id='paywall_mask']//tbody//td/span[@class='hash-tag text-truncate']/@title     from_list = tree.xpath(         https://div[@id='paywall_mask']//tbody//td/span[@class='hash-tag text-truncate']/@title)     # //div[@id='paywall_mask']//tbody//td[@class='text-center']/span/text()     transfer_type_list = tree.xpath(https://div[@id='paywall_mask']//tbody//td[@class='text-center']/span/text())     # //div[@id='paywall_mask']//tbody//td/span/span[@class='hash-tag text-truncate']//text()     to_list = tree.xpath(https://div[@id='paywall_mask']//tbody//td/span/span[@class='hash-tag text-truncate']//text())     # //div[@id='paywall_mask']//tbody//td/span[@class='small text-secondary']/text()[2]     transfer_free_list = tree.xpath(         https://div[@id='paywall_mask']//tbody//td/span[@class='small text-secondary']/text()[2])

然后就是利用redis,對txn_hash去重,去重的原因是防止一條數據被爬到了多次

def add_txn_hash_to_redis(txn_hash):     red = redis.Redis(host='根據你自己的配置', port=6379, db=0)     res = red.sadd('txn_hash:txn_set', get_md5(txn_hash))     # 如果返回0,這說明插入不成功,表示有重復     if res == 0:         return False     else:         return True # 將mmsi進行哈希,用哈希去重更快 def get_md5(txn_hash):     md5 = hashlib.md5()     md5.update(txn_hash.encode('utf-8'))     return md5.hexdigest()

最后一個需要考慮的問題:交易是在增量了,也就是說,當前第二頁的數據,很可能過會就到第三頁去了。對此我的策略是不管頁數的變動。一直往下爬。全量爬完了,再從第一頁爬新增加的交易。直到遇到第一次全量爬取的txn_hash

python爬取區塊鏈瀏覽器上的交易列表數據

最后就是存入到數據庫了。這個沒啥好說的。

python爬取區塊鏈瀏覽器上的交易列表數據

以上就可以拿到轉賬列表中的txn_hash,后面還要寫一個爬蟲深入列表里面,通過txn_hash去爬取詳情頁面的信息。這個就下個文章再說,代碼還沒寫完。

發文者:鏈站長,轉載請註明出處:https://www.jmb-bio.com/4174.html

讚! (0)
Donate 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Previous 2023 年 2 月 28 日 下午 11:12
Next 2023 年 2 月 28 日 下午 11:20

相關文章

  • Uniswap v3 設計原理詳解(一):掌握 Uniswap 的核心技術!

    剛看完 Uniswap v2 的代碼,本來打算寫一個 Uniswap v2 設計與實現,結果 Uniswap v3 就發布了。趁著這個機會就先寫一個 Uniswap v3 設計與實現吧。 因為 v3 版本的實現復雜度和 v2 已經不在一個量級了,難免會有理解上的偏差,本文權當是拋磚引玉,也希望有更多的人參與討論。因為實現比較復雜,本系列會拆分成多篇文章,持續…

    2023 年 2 月 28 日
  • 函數式程式設計技術解析:使用 Rust 和 Elixir 讀寫乙太坊智慧合約!

    本系列將重點介紹兩種函數式編程語言:Rust&Elixir。本篇分享函數式編程的思想和實踐。 在這篇文章中將展示Elixir&Rust讀取以太坊智能合約的功能。重要的是,該程序不僅在以太坊上工作,而且還在任何支持EVM的區塊鏈上工作,例如,Polkadot上的Moonbeam ! Ethereumex & ExABI 我更喜歡 Eli…

    2023 年 2 月 28 日
  • 實現 NFT 中繼資料去中心化:在 OpenSea 上實現 NFT 中繼資料!

    NFT 是附有去中心化所有權的獨一無二的代幣。“誰擁有這個代幣” 這個問題由多臺計算機同時存儲并追蹤,防止有人在未經授權的情況下篡改歸屬。 然而,NFT 的相關媒介附件和內容(統稱 “NFT 元數據”)始終沒有實現去中心化,因為直接在智能合約內存儲和修改數據會產生高昂的 gas 成本。如果沒有去中心化,收藏者就無法相信某個代幣的元數據是完整且不變的。 自 2…

    2023 年 3 月 1 日
  • LiquiDEX 兩步原子切換式通訊協定解析:掌握最新區塊鏈技術!

    長話短說:LiquiDEX 是一個在 Liquid網絡上執行兩步原子交換(atomic swaps)的協議,它只需要交換方的單次交互,這極大地改善了用戶體驗。而使用該協議,我們可以構建出更復雜系統的構建塊,例如自動 OTC 交易柜臺、拍賣系統甚至去中心化交易所 (DEX)。 注:LiquiDEX的產品還不可用。 簡介:Liquid網絡和原子交換技術 Liqu…

    2023 年 2 月 28 日
  • 乙太坊的設計理念詳解:探索乙太坊的發展歷程和設計理念!

    叔塊(uncle blocks)獎勵 GHOST 協議是一項不起的創新,由 Yonatan Sompolinsky 和 Aviv Zohar 在 2013 年 10 月首次提出的。它是解決快速出塊伴生問題的第一個認真嘗試。 GHOST 的用意是解決這樣一個難題:更短的出塊時間(因此確認速度會更快)會導致有更多區塊 “過時” 因而安全性會下降 —— 因為區塊在…

    2023 年 2 月 28 日
每日鏈頭條給你最新幣圈相關資訊!