libraccio_scraper

A Flutter package to scrape book data and cover images from Libraccio.it by ISBN.
It fetches detailed book information and provides easy access to the cover preview.

Features

  • Search book details by ISBN.
  • Extracts title, author, attributes, and other metadata.
  • Downloads and previews the book cover image.
  • Simple and easy-to-use API for Flutter apps.

Getting Started

Installation

Add this to your pubspec.yaml:

dependencies:
  libraccio_scraper: ^1.0.0

Example

Here's a complete example of a Flutter app that uses the libraccio_scraper package to search for books by ISBN:

import 'package:flutter/material.dart';
import 'package:libraccio_scraper/libraccio_scraper.dart';

void main() {
  runApp(const LibraccioApp());
}

class LibraccioApp extends StatelessWidget {
  const LibraccioApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Libraccio Scraper Demo',
      theme: ThemeData(
        primarySwatch: Colors.deepOrange,
        brightness: Brightness.light,
      ),
      home: const BookSearchPage(),
    );
  }
}

class BookSearchPage extends StatefulWidget {
  const BookSearchPage({super.key});

  @override
  State<BookSearchPage> createState() => _BookSearchPageState();
}

class _BookSearchPageState extends State<BookSearchPage> {
  final _isbnController = TextEditingController();
  final _scraper = LibraccioScraper();

  BookData? _bookData;
  String? _errorMessage;
  bool _loading = false;

  void _searchBook() async {
    final isbn = _isbnController.text.trim();
    if (isbn.isEmpty) {
      setState(() {
        _errorMessage = 'Inserisci un ISBN valido.';
        _bookData = null;
      });
      return;
    }

    setState(() {
      _loading = true;
      _errorMessage = null;
      _bookData = null;
    });

    try {
      final bookData = await _scraper.fetchBookData(isbn);
      setState(() {
        _bookData = bookData;
      });
    } catch (e) {
      setState(() {
        _errorMessage = 'Errore durante la ricerca: $e';
      });
    } finally {
      setState(() {
        _loading = false;
      });
    }
  }

  Widget _buildBookDetails() {
    if (_bookData == null) return const SizedBox.shrink();

    final rawCover = _bookData!.attributes['coverImageUrl'] ?? '';
    final coverUrl = rawCover.startsWith('http')
        ? rawCover
        : 'https://www.libraccio.it$rawCover';

    return Card(
      elevation: 4,
      margin: const EdgeInsets.symmetric(vertical: 20),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            if (coverUrl.isNotEmpty)
              Center(
                child: Image.network(
                  coverUrl,
                  height: 180,
                  fit: BoxFit.contain,
                  loadingBuilder: (context, child, loadingProgress) {
                    if (loadingProgress == null) return child;
                    return const SizedBox(
                      height: 180,
                      child: Center(child: CircularProgressIndicator()),
                    );
                  },
                  errorBuilder: (context, error, stackTrace) =>
                      const Icon(Icons.broken_image, size: 180),
                ),
              ),
            const SizedBox(height: 12),
            Text(
              _bookData!.title,
              style: const TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
            ),
            if (_bookData!.author.isNotEmpty)
              Text(
                'Autore: ${_bookData!.author}',
                style: const TextStyle(fontSize: 18, fontStyle: FontStyle.italic),
              ),
            const SizedBox(height: 12),
            const Text(
              'Dettagli:',
              style: TextStyle(fontSize: 18, decoration: TextDecoration.underline),
            ),
            ..._bookData!.attributes.entries.map(
              (entry) => Padding(
                padding: const EdgeInsets.symmetric(vertical: 2),
                child: Text('${entry.key}: ${entry.value}'),
              ),
            ),
          ],
        ),
      ),
    );
  }

  @override
  void dispose() {
    _isbnController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Libraccio Book Search'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          children: [
            TextField(
              controller: _isbnController,
              decoration: const InputDecoration(
                labelText: 'ISBN',
                hintText: 'Inserisci ISBN del libro',
                border: OutlineInputBorder(),
                prefixIcon: Icon(Icons.book),
              ),
              keyboardType: TextInputType.number,
              onSubmitted: (_) => _searchBook(),
            ),
            const SizedBox(height: 16),
            ElevatedButton.icon(
              onPressed: _loading ? null : _searchBook,
              icon: const Icon(Icons.search),
              label: const Text('Cerca libro'),
              style: ElevatedButton.styleFrom(
                minimumSize: const Size.fromHeight(48),
              ),
            ),
            const SizedBox(height: 16),
            if (_loading) const CircularProgressIndicator(),
            if (_errorMessage != null)
              Text(
                _errorMessage!,
                style: const TextStyle(
                    color: Colors.red, fontWeight: FontWeight.bold),
              ),
            Expanded(
              child: SingleChildScrollView(
                child: _buildBookDetails(),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

This example demonstrates:

  • How to set up a simple Flutter app using the libraccio_scraper package
  • Creating a search interface with an ISBN input field
  • Implementing the book search functionality
  • Displaying book details including cover image
  • Error handling for invalid ISBNs or network issues
  • Proper state management during loading states

To use this example:

  1. Create a new Flutter project
  2. Add libraccio_scraper as a dependency in your pubspec.yaml
  3. Replace the contents of lib/main.dart with the code above
  4. Run the app and enter a valid ISBN to search for a book

Libraries

libraccio_scraper