fix facebook feed zero rows after decoy filter - #4
Conversation
Live smoke after PR #3 hit no_rows with articles=2 because decoy filtering dropped scrambled posts in-page without surfacing why. Add French action-menu and metric labels, fix dedupe skipping author-only decoy containers, and record per-article rejection reasons (decoy/suggestion/messenger/etc). When all candidates are decoys, fail with anti-scrape error even at zero rows; otherwise include rejection breakdown in the generic no_rows hint. Co-authored-by: Tom Coustols <tom.coustols@tcdynamics.fr>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueThanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Reviewer's GuideThe extractor now supports French Facebook feed markup, preserves candidates rejected by readability and scope checks for diagnostics, and distinguishes all-decoy zero-row results from other extraction failures with actionable error details. Sequence diagram for Facebook feed extraction diagnosticssequenceDiagram
participant FacebookPage
participant Extractor
participant FeedCommand
participant CLI
FacebookPage->>Extractor: buildFeedExtractScript(limit)
Extractor->>Extractor: dedupe containers with fallback keys
Extractor->>Extractor: extractPost(container)
alt readable post
Extractor-->>FeedCommand: rows and diagnostics
FeedCommand-->>CLI: extracted feed rows
else rejected candidate
Extractor->>Extractor: rejectionSample(container)
Extractor-->>FeedCommand: no_rows and diagnostics.rejections
FeedCommand->>FeedCommand: summarizeFeedRejections(diagnostics)
alt all candidates are decoys
FeedCommand-->>CLI: CommandExecutionError anti-scrape decoy
else other candidates rejected
FeedCommand-->>CLI: CommandExecutionError with rejection breakdown
end
end
Flow diagram for French Facebook feed extractionflowchart TD
A[Facebook feed markup] --> B[Recognize French labels and metrics]
B --> C[Find author and content blocks]
C --> D{Readable candidate?}
D -->|Yes| E[Build feed row]
D -->|No| F[Record rejection reason author and snippet]
E --> G[Return extracted rows]
F --> H{All rejections are decoys?}
H -->|Yes| I[Raise anti-scrape decoy error]
H -->|No| J[Raise no-rows error with counts and samples]
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 2 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="clis/facebook/feed.js" line_range="902" />
<code_context>
+ ).length,
mainTextLength: textOf(document.querySelector('[role="main"]')).length,
feedFound: !!document.querySelector('[role="main"] [role="feed"], [role="feed"]'),
+ rejections: rejections.slice(0, 12),
surface,
},
</code_context>
<issue_to_address>
**issue (broader_impact):** The extractor truncates rejection diagnostics to the first 12 entries before Node classifies them with `allDecoy`. If the first 12 candidates are decoys but a later rejected candidate has another reason, the omitted candidate cannot prevent the command from incorrectly raising the all-decoy anti-scrape error.
**Triggers:** When more than 12 candidate articles are rejected and the first 12 are decoys.
**Suggested fix:** Compute the rejection summary from all candidates and truncate only the diagnostic payload presented to the caller.
</issue_to_address>
### Comment 2
<location path="clis/facebook/feed.js" line_range="897-899" />
<code_context>
actionMenuCount: actionMenuAnchors().length,
- fallbackActionCount: document.querySelectorAll('[role="main"] [aria-label="Like"], [role="main"] [aria-label="赞"], [role="main"] [aria-label="Comment"], [role="main"] [aria-label="评论"]').length,
+ fallbackActionCount: document.querySelectorAll(
+ '[role="main"] [aria-label="Like"], [role="main"] [aria-label="赞"], [role="main"] [aria-label="J\\'aime"], '
+ + '[role="main"] [aria-label="Comment"], [role="main"] [aria-label="评论"], [role="main"] [aria-label="Commenter"]',
+ ).length,
mainTextLength: textOf(document.querySelector('[role="main"]')).length,
feedFound: !!document.querySelector('[role="main"] [role="feed"], [role="feed"]'),
</code_context>
<issue_to_address>
**nitpick:** The French fallback selector counts `J'aime`, `Commenter`, and the other like/comment labels but omits the newly supported `Partager` label, even though `fallbackContainers` recognizes it. A French page whose visible fallback evidence includes share actions therefore reports an incomplete `actions` diagnostic and can lose that action evidence in no-row classification.
**Triggers:** When French feed markup exposes `Partager` as the relevant fallback action and the other counted action labels are absent.
**Suggested fix:** Add `[aria-label="Partager"]` to the `fallbackActionCount` selector, keeping it aligned with `fallbackContainers`.
</issue_to_address>Sourcery assessment
Approval pending. 1 finding to address first.
Blocking findings: clis/facebook/feed.js:902
| ).length, | ||
| mainTextLength: textOf(document.querySelector('[role="main"]')).length, | ||
| feedFound: !!document.querySelector('[role="main"] [role="feed"], [role="feed"]'), | ||
| rejections: rejections.slice(0, 12), |
There was a problem hiding this comment.
issue (broader_impact): The extractor truncates rejection diagnostics to the first 12 entries before Node classifies them with allDecoy. If the first 12 candidates are decoys but a later rejected candidate has another reason, the omitted candidate cannot prevent the command from incorrectly raising the all-decoy anti-scrape error.
Triggers: When more than 12 candidate articles are rejected and the first 12 are decoys.
Suggested fix: Compute the rejection summary from all candidates and truncate only the diagnostic payload presented to the caller.
| '[role="main"] [aria-label="Like"], [role="main"] [aria-label="赞"], [role="main"] [aria-label="J\\'aime"], ' | ||
| + '[role="main"] [aria-label="Comment"], [role="main"] [aria-label="评论"], [role="main"] [aria-label="Commenter"]', | ||
| ).length, |
There was a problem hiding this comment.
nitpick: The French fallback selector counts J'aime, Commenter, and the other like/comment labels but omits the newly supported Partager label, even though fallbackContainers recognizes it. A French page whose visible fallback evidence includes share actions therefore reports an incomplete actions diagnostic and can lose that action evidence in no-row classification.
Triggers: When French feed markup exposes Partager as the relevant fallback action and the other counted action labels are absent.
Suggested fix: Add [aria-label="Partager"] to the fallbackActionCount selector, keeping it aligned with fallbackContainers.
Description
After PR #3, live smoke on tom.coustols stopped returning scrambled Adolph decoys (good) but started failing with
no feed rows could be extracteddespitearticles=2, actions=1, mainTextLength=976. The in-page extractor was rejecting scrambled posts before rows were built, so Node never saw decoy rows and fell through to the generic error.Related: live smoke 2026-09-11, OpenCLI ae8e790
Type of Change
Changes
Actions pour cette publication par …, J'aime/Commenter/Partager, Tous:/commentaires/partages, Partagé avec Publicdiagnostics.rejections[]with reason/author/snippet per candidate (decoy_content, suggestion, messenger, insufficient_evidence, comment_thread, etc.)CommandExecutionErrorwithdecoy_content=Nbreakdownrejected=N, reason=count, samples=…when articles exist but nothing extractsChecklist
npm test -- clis/facebook/— 112 passed (includes Adolph/decoy + French fixtures)Post-merge verification
On tom.coustols desk:
opencli facebook feed --limit 5should either return readable posts (e.g. LVLUP with Lani) OR fail withdecoy_content=2/ rejection samples — not a barearticles=2hint with no explanation.Summary by Sourcery
Improve Facebook feed extraction to support French content and explain zero-row results caused by filtered or unreadable posts.
Bug Fixes:
Enhancements:
Tests:
Summary by cubic
Fixes the Facebook feed extractor returning zero rows after decoy filtering, so live feeds with scrambled posts now either return readable posts or fail with a clear anti-scrape error instead of a bare no-rows hint.
Changes
decoy_content,suggestion,messenger, etc.) in diagnostics.CommandExecutionErrorwhen all candidates are decoys, even at zero rows.Written for commit 61a0b99. Summary will update on new commits.