在JS中使用Cheerio提取含动态类名元素的URL方法问询
Great question! Dealing with elements that have dynamic class names (like those with embedded IDs or random strings) is a super common scraping scenario—let’s break down exactly how to tackle this in Cheerio, including wildcard-style matching.
1. Use CSS Attribute Selectors for Partial Class Matches
Cheerio supports CSS attribute selectors that let you match parts of a class name, which is perfect for dynamic classes with fixed prefixes/suffixes. Here are the most useful ones:
[class^="prefix-"]: Matches elements where the class starts withprefix-[class$="-suffix"]: Matches elements where the class ends with-suffix[class*="contains-this"]: Matches elements where the class contains the substring anywhere
For example, if you have elements like <div class="item-card-789"> where item-card- is fixed but the number changes, you can target them directly and extract the nested URL:
const cheerio = require('cheerio'); const html = ` <div class="item-card-123"> <a href="/products/123">Red Widget</a> </div> <div class="item-card-456"> <a href="/products/456">Blue Gadget</a> </div> `; const $ = cheerio.load(html); // Target all divs with classes starting with "item-card-" $('[class^="item-card-"]').each((idx, el) => { const productUrl = $(el).find('a').attr('href'); console.log(`Found product URL: ${productUrl}`); });
2. Filter Elements with Regular Expressions
If you need more control (like matching complex patterns), use Cheerio’s .filter() method combined with a regex to check the class name. This is handy when the dynamic part is in the middle of the class, or you need exact pattern matching:
// Match any div where the class includes "item-card" followed by numbers $('div').filter((idx, el) => { return /item-card-\d+/.test($(el).attr('class')); }).each((idx, el) => { const productUrl = $(el).find('a').attr('href'); console.log(`Regex-matched URL: ${productUrl}`); });
3. Leverage Fixed Companion Classes
If the dynamic class is paired with a static class (e.g., <div class="product-card dynamic-987">), skip the dynamic part entirely and target the static class—this is the simplest approach when available:
// Target the static "product-card" class directly $('.product-card').each((idx, el) => { const productUrl = $(el).find('a').attr('href'); console.log(`Static class URL: ${productUrl}`); });
How This Compares to Your itemprop Workflow
You mentioned you already handle elements with dynamic itemprop contexts—this class-based approach follows the same logic: instead of targeting [itemprop="url"], you’re targeting partial matches on the class attribute. The core idea is using CSS selectors or regex to zero in on the fixed part of the dynamic attribute value.
Pro Tips
- Be specific with your selectors (e.g., use
div[class^="item-card-"]instead of just[class^="item-card-"]) to avoid matching unintended elements. - If class names have multiple space-separated values,
[class*="item-card"]will still work (it matches substrings, not whole class names), but use^or$if you need to match the start/end of the class attribute string.
内容的提问来源于stack exchange,提问作者froggomad

