Symfony Console Command를 사용한 웹사이트 스크래핑 (클린 및 프로덕션 친화적)
Source: Dev.to
Introduction
웹 스크래핑은 컨트롤러에 넣어서는 안 됩니다.
오래 실행될 수 있고, 실패할 수도 있으며, 보통 스케줄링되며, 본질적으로 자동화 작업이기 때문입니다.
Symfony 콘솔 명령은 Symfony 애플리케이션 내부에서 실행되면서 서비스와 의존성 주입 컨테이너에 완전히 접근할 수 있기 때문에 이 시나리오에 최적입니다.
What the command does
- 무료 샌드박스 사이트에서 국가 데이터를 스크랩합니다.
- DomCrawler 로 HTML을 파싱합니다.
- 결과를 알파벳 순으로 정렬합니다.
- 깔끔한 CLI 테이블로 출력합니다.
GitHub 저장소를 따라가며 실습할 수 있습니다:
데모에 사용된 스크래핑 샌드박스:
Prerequisites
composer require symfony/http-client
composer require symfony/dom-crawler
composer require symfony/css-selector
Create the console command
php bin/console make:command app:create-countries
Inject the HTTP client (DI)
use Symfony\Contracts\HttpClient\HttpClientInterface;
public function __construct(
private HttpClientInterface $client
) {}
Fetch the page
$response = $this->client->request('GET', self::URL);
$html = $response->getContent(); // raw HTML
Parse with DomCrawler
use Symfony\Component\DomCrawler\Crawler;
$crawler = new Crawler($html);
Extract country information
$countryInfo = [];
$crawler->filter('.country')->each(function (Crawler $row) use (&$countryInfo) {
$countryInfo[] = [
$row->filter('.country-name')->text(),
$row->filter('.country-capital')->text(),
$row->filter('.country-population')->text(),
$row->filter('.country-area')->text(),
];
});
Sort alphabetically by country name
usort($countryInfo, function ($a, $b) {
return strcasecmp($a[0], $b[0]);
});
Display results in a formatted table
// Header
printf(
"%-45s | %-20s | %15s | %15s\n",
"Country name",
"Capital",
"Population",
"Area (km2)"
);
// Rows
foreach ($countryInfo as $row) {
printf(
"%-45s | %-20s | %15s | %15s\n",
$row[0],
$row[1],
$row[2],
$row[3]
);
}
Tip: 유니코드 문자와 정렬을 맞추려면 멀티바이트‑안전 패딩 헬퍼를 추가하세요.
Run the command:
php bin/console app:create-countries
전문적인 터미널 테이블 형태의 출력이 나타나며, 원시 디버그 데이터는 보이지 않을 것입니다.
Benefits of this approach
- 관심사의 분리 – 스크래핑 로직이 컨트롤러 밖에 존재합니다.
- Cron‑친화적 – cron이나 Symfony 스케줄러로 쉽게 예약할 수 있습니다.
- 깨끗한 아키텍처 – 재사용 가능하고, 테스트 가능하며, 유지 보수가 쉬운 코드입니다.
- 확장성 – 필요에 따라 비동기 작업으로 리팩터링할 수 있습니다.
Scraping etiquette (before targeting real sites)
- 사이트의 서비스 약관을 확인하세요.
robots.txt를 준수하세요.- 과도한 요청 속도를 피하고, 여러 페이지를 스크랩할 경우 딜레이를 추가하세요:
sleep(1); // pause 1 second between requests
Full source code
명령 구현, 포맷팅 헬퍼, 설정 안내 등을 포함한 완전한 작업 프로젝트는 GitHub에서 확인할 수 있습니다:
When to use this pattern
- 데이터 집계 도구
- 모니터링 시스템
- 인텔리전스 플랫폼
- 백그라운드 자동화 작업
Symfony 콘솔 명령과 DomCrawler 를 결합하면 이러한 사용 사례에 대해 과소평가되지만 강력한 솔루션을 제공할 수 있습니다.
Next steps
시리즈 2부에서는 스크랩한 결과를 데이터베이스에 저장하는 방법을 다룰 예정입니다.