Ported from Discord bot's async web fetcher improvements. Add comprehensive logging to understand crawl behavior: - Log crawl parameters at start (max_depth, URLs, keywords) - Debug log for crawl queue state during processing - Detailed link extraction stats with skip reasons: - Total links found - Links added to crawl queue - Links skipped by robots.txt - Links skipped (wrong domain) - Links skipped (max depth reached) Applied to both: - Fresh page fetching and link extraction - Cached page link extraction for depth traversal This diagnostic logging helps identify why crawlers find fewer pages than expected (e.g., robots.txt blocking, domain filtering, depth limits). No crawl logic changes - purely diagnostic visibility.
5.5 KiB
Changelog
All notable changes to the Unturf Spider project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Detailed crawl diagnostic logging: Added comprehensive logging to diagnose crawl behavior
- Log crawl parameters at start (max_depth, initial URLs count, query keywords)
- Debug log showing crawl queue state during processing
- Detailed link extraction statistics (total found, added to queue, skipped by reason)
- Separate counters for links skipped due to: robots.txt, wrong domain, or max depth reached
- Applied to both fresh page fetching and cached page link extraction
- Located in
unturf_spider.py:611-613(crawl_recursive start logging) - Located in
unturf_spider.py:547(cached page link extraction logging) - Located in
unturf_spider.py:596(fresh page link extraction logging)
Fixed
- Critical depth traversal bug: Fixed issue where cached pages at depth 0 would not extract links, preventing depth 1+ crawling
- When a page was already cached and
force_crawl=False, the crawler would return early without extracting links - This broke depth-based crawling: if the starting URI was cached, no depth 1 pages would be discovered
- Now the crawler still extracts links from cached pages when
depth < max_depthto enable proper depth traversal - Example: With
depth=1and a cached starting page, the crawler now correctly discovers and crawls linked pages - Located in
unturf_spider.py:501-539(new cached page link extraction logic)
- When a page was already cached and
Added
-
Query-aware page scoring system: Pages are now scored based on content quality and relevance to the user's query
- Multi-factor scoring algorithm (0-100+ points):
- Content length (0-30 points) - Substantial content gets higher scores
- Title quality (0-15 points) - Descriptive titles score higher
- URL quality (0-15 points) - Clean, readable URLs preferred
- Content density (0-15 points) - Unique word ratio indicates quality
- Query relevance (0-40 points) - Keyword matches in title, URL, and content
- New
_score_page()method inBaseCrawlerclass (lines 130-223) - Query keywords are extracted once at the beginning using Hermes AI model
- Keywords are passed through the entire crawl chain for real-time scoring
- Multi-factor scoring algorithm (0-100+ points):
-
Database schema enhancement: Added
scorefield toArticlemodel- Stores integer quality/relevance score (0-100+)
- Default value: 0
- Nullable to maintain backward compatibility
- SQLAlchemy will auto-migrate on first run
Changed
-
cache_article()method: Now acceptsscoreparameter and stores it in database- Located in
unturf_spider.py:431-478 - Updated log messages to include score information
- Located in
-
process_url()method: Calculates page score and passes it tocache_article()- Located in
unturf_spider.py:480-556 - Accepts
query_keywordsparameter for scoring - Creates page_data dict with url, title, and text for scoring
- Logs score for each processed page
- Located in
-
crawl_recursive()method: Threadsquery_keywordsparameter through crawl chain- Located in
unturf_spider.py:558-585 - Passes keywords to all
process_url()calls
- Located in
-
DuckDuckGoCrawler.run()method: Extracts query keywords early for scoring- Located in
unturf_spider.py:849-874 - Uses
_extract_keywords_with_hermes()before starting crawl - Passes keywords to
crawl_recursive()
- Located in
-
DirectTargetCrawler.run()method: Extracts query keywords early for scoring- Located in
unturf_spider.py:912-926 - Uses
_extract_keywords_with_hermes()before starting crawl - Passes keywords to
crawl_recursive()
- Located in
Technical Details
-
Keyword extraction: Uses Hermes AI model to intelligently extract relevant keywords from user queries
- Filters out stop words and generic terms
- Focuses on domain-specific and technical terms
- Returns 3-7 most relevant keywords for scoring
-
Real-time scoring: Pages are scored during crawling (not after)
- Enables future enhancements like selective crawling based on score
- Allows prioritization of high-quality, relevant content
- Provides visibility into crawl quality through logs
Future Enhancements (Deferred)
-
Async/await conversion: Replace
requestswithaiohttpfor concurrent crawling- Would improve performance significantly
- Requires substantial refactor of fetching logic
- Lower priority than scoring integration
-
Progressive depth escalation: Dynamically increase crawl depth based on initial results
- Start with depth=1, escalate to depth=2 if needed
- Adaptive crawling based on content quality
- Reduces unnecessary crawling
Migration Notes
- Database migration: The new
scorecolumn will be added automatically by SQLAlchemy on first run - Backward compatibility: Existing cached articles will have
score=0until re-crawled - No breaking changes: All existing functionality remains intact
Performance Impact
- Minimal overhead: Scoring adds ~10ms per page (negligible compared to network I/O)
- One-time keyword extraction: Keywords are extracted once per query, not per page
- No network calls: Scoring is purely computational using already-fetched content
[1.42] - Previous Release
- Initial stable release with basic crawling functionality
- Hermes AI-powered content extraction
- SQLite caching with TTL
- robots.txt compliance
- DuckDuckGo and direct target crawling modes