承接 wiserwebsolutions/laravel-boarddocs-scraper 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

wiserwebsolutions/laravel-boarddocs-scraper

Composer 安装命令:

composer require wiserwebsolutions/laravel-boarddocs-scraper

包简介

A Laravel package that scans public BoardDocs sites for agendas and attachments, exposes a fluent unofficial API, and exports self-contained meeting PDFs with remote links rewritten as in-document anchors.

README 文档

README

AI-authored notice The initial commit of this project was made by an AI assistant that was asked to convert specific components of a private Python script into a publishable Laravel package.

A Laravel package that scans public BoardDocs sites for meeting agendas and attachments, exposes a fluent, Laravel-flavored "unofficial API," and exports self-contained meeting PDFs — with remote BoardDocs links rewritten into in-document anchors — plus a JSONL search index that plugs into the Laravel AI SDK.

It is a PHP/Laravel port of the Python AbandonBoard exporter, so a district can archive its agendas before losing BoardDocs access. Public data only — the private/login features of the original are intentionally omitted.

BoardDocs()->site('pa/phoe')
    ->committees()->first()
    ->agenda()->withAttachments()
    ->toPdf()
    ->save();

Requirements

  • PHP 8.2+
  • Laravel 11, 12, or 13
  • tecnickcom/tcpdf + setasign/fpdi (installed automatically) for PDF assembly

Installation

composer require graboyes/laravel-boarddocs-scraper
php artisan vendor:publish --tag=boarddocs-config

Set your default site in .env:

BOARDDOCS_SITE="pa/phoe"

The fluent API

The BoardDocs() helper (or the BoardDocs facade) is the entry point. Committee and meeting lists are returned as Laravel Collections and are cached, so ->first(), ->firstWhere(), ->map() etc. all work as expected.

use BoardDocsScraper\Facades\BoardDocs;

// Discover committees (cached)
$committees = BoardDocs::site('pa/phoe')->committees();      // Collection<Committee>
$board = BoardDocs::site('pa/phoe')->committeeNamed('Directors');

// Meetings for a committee (newest first, cached)
$meetings = $board->meetings();                              // Collection<Meeting>
$latest   = $board->latest();                                // ?Meeting

// Agenda for a meeting
$agenda = $latest->agenda();
$agenda->items();          // Collection<AgendaItemData>
$agenda->attachments();    // Collection<AttachmentData> (metadata; no download)
$agenda->text();           // plain-text agenda summary

// Render a self-contained PDF
$pdf = $agenda->withAttachments()->toPdf();
$pdf->pageCount();                     // int
$pdf->attachments();                   // SavedAttachment[]
$pdf->save();                          // -> "boarddocs/pa-phoe/Public/<committee>/<date>-Agenda.pdf"
$pdf->save('custom/path.pdf', 'r2');   // any Laravel disk
return $pdf->response();               // inline PDF HTTP response

The one-liner from the top works too:

BoardDocs()->site('pa/phoe')->committees()->first()->agenda()->withAttachments()->toPdf();

The low-level HTTP client (the raw "unofficial API") is available if you need it:

$client = BoardDocs::client('pa/phoe');
$client->discoverCommittees();
$client->listMeetings($committeeId);
$client->fetchPrintAgendaHtml($meetingId, $committeeId);

Self-contained meeting PDFs

With self_contained enabled (default), each meeting PDF contains the printed agenda followed by every PDF attachment merged inline, one bookmark per attachment, and non-PDF attachments embedded as file attachments. When remap_links is on, any remote BoardDocs link in the agenda is rewritten into an internal PDF anchor that jumps to the merged attachment's page — so the document stays fully navigable offline, even if a district's BoardDocs subscription ends.

Two rendering engines are available (configure boarddocs.pdf.engine):

Engine Fidelity Link remap Dependencies
tcpdf (default) Good (agenda pages are simple) ✅ Yes pure PHP
browsershot High (real Chrome) ❌ No (attachments still merged) spatie/browsershot + Node + Chromium

Scanning & the search index

# Export a whole site (all committees), updating output/index.jsonl
php artisan boarddocs:scan --site=pa/phoe

# Scope it
php artisan boarddocs:scan --site=pa/phoe --committee=CTNNDT5F7A3B --limit=5 --since=2024-01-01
php artisan boarddocs:scan --dry-run          # list without downloading
php artisan boarddocs:scan --no-attachments   # agenda-only PDFs
php artisan boarddocs:scan --engine=browsershot

# Search the exported index
php artisan boarddocs:search budget transportation --committee=Finance --limit=10

index.jsonl has the same shape as the original project (one meeting per line):

{"path":"pa-phoe/Public/Policy Committee/2026-06-01-Agenda.pdf","district":"pa-phoe",
 "visibility":"Public","committee":"Policy Committee","date":"2026-06-01","page_count":7,
 "agenda_text":"","attachments":[{"title":"May 18, 2026 Policy Minutes.pdf","page":4}]}

Meetings whose PDF already exists are skipped, except those within scan.refresh_recent_days (default 30) which are re-exported.

Laravel AI SDK integration

The package ships ready-to-use AI SDK tools so an agent can search and consume the archive. Install the SDK to use them:

composer require laravel/ai

Use the bundled agent directly:

use BoardDocsScraper\Ai\BoardDocsAgent;

$answer = (new BoardDocsAgent)->prompt('What did the Policy Committee decide about edtech?');

…or register the individual tools on your own agent:

use BoardDocsScraper\Ai\Tools\SearchAgendasTool;
use BoardDocsScraper\Ai\Tools\GetMeetingTool;
use BoardDocsScraper\Ai\Tools\ListCommitteesTool;

class MyAgent implements Agent, HasTools
{
    use Promptable;

    public function tools(): iterable
    {
        return [new SearchAgendasTool, new GetMeetingTool, new ListCommitteesTool];
    }
}
  • SearchAgendasTool — keyword search over agenda text + attachment titles; returns meetings with snippets and the path to fetch full details.
  • GetMeetingTool — full indexed record (agenda text, attachments + pages) for one path.
  • ListCommitteesTool — live committee list for a site.

Configuration

See config/boarddocs.php. Highlights:

Key Purpose
site, base_url Default site slug and host
http.request_delay Polite delay between requests (seconds)
cache.store, cache.ttl Cache store + TTL for committee/meeting/agenda data
output.disk, output.path, output.index Where PDFs and index.jsonl are written
pdf.engine tcpdf or browsershot
pdf.self_contained, pdf.remap_links, pdf.embed_non_pdf Self-contained PDF behavior
scan.refresh_recent_days Re-export window for recent meetings

Testing

composer install
vendor/bin/pest

License

MIT

统计信息

  • 总下载量: 0
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 1
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-08

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固