使用解析器选择器从动态网络 table 抓取数据

Scrape data from a dynamic web table using parsel selector

我正在尝试获取 'From' 列中任何令牌的首次交易地址。由于经常有新交易,因此使 table 动态化,我希望能够使用解析器选择器随时获取此信息。这是我尝试过的方法:

第一步:获取总页数

第二步:将该数字插入 URL 以获得最早的页码。

第三步:遍历'From'列,提取第一个地址。

它returns 一个空列表。我无法弄清楚问题的根源。任何建议将不胜感激。

from parsel import Selector

contract_address = "0x431e17fb6c8231340ce4c91d623e5f6d38282936"
 
pg_num_url = f"https://bscscan.com/token/generic-tokentxns2?contractAddress={contract_address}&mode=&sid=066c697ef6a537ed95ccec0084a464ec&m=normal&p=1"
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"}
response = requests.get(pg_num_url, headers=headers) 
sel = Selector(response.text)

pg_num = sel.xpath('//nav/ul/li[3]/span/strong[2]').get()  # Attempting to extract page number 

url = f"https://bscscan.com/token/generic-tokentxns2?contractAddress={contract_address}&mode=&sid=066c697ef6a537ed95ccec0084a464ec&m=normal&p={pg_num}"  # page number inserted
response = requests.get(url, headers=headers) 
sel = Selector(response.text)

addresses = []
for row in sel.css('tr'):
    addr = row.xpath('td[5]//a/@href').re('/token/([^#?]+)')[0][45:]
    addresses.append(addr)

print(addresses[-1])  # Desired address

似乎该网站正在使用服务器端会话跟踪和安全令牌来增加抓取难度。

我们可以通过复制他们的行为来解决这个问题!
如果您查看 Web Inspector,您会发现在我们第一次连接到该网站时,一些 cookie 会发送给我们:

此外,当我们在其中一个 table 上单击下一页时,我们会看到这些 cookie 被发送回服务器:

最后,table 页面的 url 包含一个叫做 sid 的东西,它通常代表类似 security id 的东西,可以在第一页正文中找到。如果您检查页面源代码,您会发现它隐藏在 javascript:

现在我们需要将所有这些放在一起:

  1. 启动一个请求Session,它将跟踪 cookie
  2. 转到令牌主页并接收 cookie
  3. 在代币主页找到sid
  4. 使用 cookie 和 sid 令牌抓取 table 页面

我已经修改了你的代码,它最终看起来像这样:

import re
import requests
from parsel import Selector

contract_address = "0x431e17fb6c8231340ce4c91d623e5f6d38282936"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36"
}

# we need to start a session to keep track of cookies
session = requests.session()
# first we make a request to homepage to pickup server-side session cookies
resp_homepage = session.get(
    f"https://bscscan.com/token/{contract_address}", headers=headers
)
# in the homepage we also need to find security token that is hidden in html body
# we can do this with simple regex pattern:
security_id = re.findall("sid = '(.+?)'", resp_homepage.text)[0]

# once we have cookies and security token we can build the pagination url
pg_num_url = (
    f"https://bscscan.com/token/generic-tokentxns2?"
    f"contractAddress={contract_address}&mode=&sid={security_id}&m=normal&p=2"
)

# finally get the page response and scrape the data:
resp_pagination = session.get(pg_num_url, headers=headers)

addresses = []
for row in Selector(resp_pagination.text).css("tr"):
    addr = row.xpath("td[5]//a/@href").get()
    if addr:
        addresses.append(addr)
print(addresses)  # Desired address