【问题标题】:one selector gets all elements, but the other doesn't get all elements on the page一个选择器获取所有元素,但另一个没有获取页面上的所有元素
【发布时间】:2022-01-16 21:47:19
【问题描述】:

(根据cmets的建议修改)

我正在尝试做的事情:网络抓取以从 this website 获取所有 100 个加密货币名称。

问题:我使用的选择器没有选择页面上的所有加密名称。只选择了其中的一部分。

在那个网页中,有 100 行,每一行都有一个加密货币名称。总共有 100 个名字。

如果我使用这个选择器tr td a[href*="/currencies/"][href$="/"]:not([href$="/markets/"])

它会在页面上找到所有 100 个元素,我可以从这 100 个元素中获取每个加密货币的 URL。 (一页有 100 种加密货币)

所选 100 个元素的一个样本:

<a href="/currencies/ethereum/" class="cmc-link"><div class="sc-16r8icm-0 sc-1teo54s-0 dBKWCw"><img class="coin-logo" src="https://s2.coinmarketcap.com/static/img/coins/64x64/1027.png" loading="lazy" alt="ETH logo"><div class="sc-16r8icm-0 sc-1teo54s-1 dNOTPP"><p font-weight="semibold" color="text" font-size="1" class="sc-1eb5slv-0 iworPT">Ethereum</p><div class="sc-1teo54s-2 fZIJcI"><div class="sc-1teo54s-3 etWhyV">2</div><p color="text3" class="sc-1eb5slv-0 gGIpIK coin-item-symbol" font-size="1">ETH</p></div></div></div></a>

-到目前为止没问题。

但是,如果我将 &gt;div&gt;div&gt;p 添加到此选择器以获取每个加密名称,

(tr td a[href*="/currencies/"][href$="/"]:not([href$="/markets/"])&gt;div&gt;div&gt;p),

只选择了 19 个元素,而不是全部 100 个元素。

所选元素的一个示例:

<p font-weight="semibold" color="text" font-size="1" class="sc-1eb5slv-0 iworPT">Ethereum</p>

如果我向下滚动页面,所选元素的数量会增加,但我想要的是在没有滚轮滚动的情况下获得所有 100 个元素。

  1. 为什么第一个选择器会立即找到整个元素,而第二个选择器需要向下滚动页面?
  2. 我应该使用什么选择器来选择所有 100 个加密货币名称而不向下滚动?

提前致谢:)

(我正在尝试使用 Playwright 进行网页抓取,但我认为这只是关于 CSS 选择器的一般问题)

【问题讨论】:

  • “如果我向下滚动页面,所选元素的数量会增加” - 所以只有在滚动到它们时才会将它们添加到 DOM 中。应该很容易验证。
  • @Andreas 你是对的。我使用的选择器没有错,它们只是正确地工作。感谢您的评论。

标签: javascript html jquery css web-scraping


【解决方案1】:

这不是 css 选择器的问题。这是一个动态加载的页面,因此您需要调用 API 来获取其内容

https://api.coinmarketcap.com/data-api/v3/map/all?listing_status=active,untracked&exchangeAux=is_active,status&cryptoAux=is_active,status&start=10001&limit=10000

一旦你这样做,你会得到一个 json。例如,要从中提取货币代码,您需要

const obj = JSON.parse(response);
curs = obj['data']['cryptoCurrencyMap']

如果你跑了

for (let cur of curs)
   {console.log(cur['symbol'])}

你应该得到不少代码...

【讨论】:

  • 谢谢,这是一个更好的方法。我正在尝试在硬币名称(来自 API)和它们的 URL 之间创建一个映射。即 {"Bitcoin": "https:.../bitcoin/", "Ethereum": "https..."}。你能给我一个提示吗?我不认为 API 提供了每个硬币的 URL(但我成功地从网页收集了 URL)。
  • @starriet 硬币的 URL 确实不在响应中。很难抽象地回答,但要做到你想要的,你需要一个数组中的硬币名称,另一个数组中的 URL,然后在它们上使用 map()。您也可以将其作为一个单独的问题发布,使用带有 3-4 个硬币名称的数组和另一个带有各自 URL 的数组作为示例。
  • 不知何故我设法做到了,谢谢!
  • @starriet 很高兴听到!
猜你喜欢
  • 1970-01-01
  • 2012-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-20
相关资源
最近更新 更多