카테고리 허브 제작, 색인 요청, 사이트맵 정제, 내부 링크 개편을 하다 보면 “표준 URL 목록”과 “제목 매핑”이 꼭 필요합니다. 이 글은 티스토리 관리자 페이지의 글 목록 화면에서 개발자 도구를 이용해 URL을 대량 추출하는 방법과, 추출한 URL(전체 URL 기준)을 파이썬으로 읽어 각 페이지의 제목을 자동 수집하는 방법을 정리했습니다. 실무에서 바로 쓰는 안전한 절차로 구성했습니다.
---
1) 관리자 페이지에서 글 URL 한 번에 추출하기(개발자 도구)
목적
- 관리자 글 목록 화면에 렌더링된 글 링크(a href) 중 “표준 URL(PC 기준)”만 수집합니다.
- /m/, 파라미터(?), 태그/검색/아카이브/공지 등 변형·목록 URL은 제외합니다.
사전 준비
- 대상 화면: 티스토리 관리자 → 글 목록
- Console 보안 경고 해결: 콘솔 입력창에 allow pasting 입력 → Enter
순서
1) 관리자 글 목록 페이지 열기
2) 키보드 F12 → 개발자 도구 → Console 탭
3) allow pasting 입력 → Enter
4) 아래 코드를 복사→붙여넣기→Enter
콘솔 코드(표준 URL 일괄 추출)
*. 아래 코드블럭의 "eyehole.tistory.com"은 본인 블로그 주소로 변경
(() => {
const base = Array.from(document.querySelectorAll('a'))
.map(a => a.href)
.filter(u => u && u.startsWith('https://eyehole.tistory.com/'))
.filter(u =>
!u.includes('/m/') &&
!u.includes('?') &&
!/\/tag\/|\/search|\/archive|\/notice\//.test(u)
);
// 숫자형 주소(권장) + 슬러그 주소(혼용 시 대비)
const numeric = base.filter(u => /https:\/\/eyehole\.tistory\.com\/\d+$/.test(u));
const slug = base.filter(u => /https:\/\/eyehole\.tistory\.com\/[A-Za-z0-9\-\._%]+$/.test(u));
const all = Array.from(new Set([...numeric, ...slug]));
console.table(all.map((u, i) => ({ idx: i + 1, url: u })));
return all;
})();

팁
- 페이지네이션이면 각 페이지에서 실행 후 결과를 합치세요.
- 무한 스크롤이면 맨 아래까지 스크롤해 모든 글이 로딩된 상태에서 실행하세요.
- 콘솔 출력의 표에서 복사하거나, 반환된 배열을 우클릭 → Copy object로 복사하세요.
---
2) 전체 URL을 바로 파싱: 파이썬으로 제목 자동 수집
설명
- ids.txt에 “전체 URL”을 한 줄에 하나씩 저장합니다.
- 스크립트는 /m/, 파라미터, 태그/검색/아카이브/공지 경로를 자동 정규화·제외합니다.
- 결과는 titles.csv(url, title, canonical_url)로 저장됩니다.
사전 준비
- Python 3.x 설치
- 라이브러리 설치
pip install requests beautifulsoup4
입력 파일(ids.txt) 예시
https://eyehole.tistory.com/1006
https://eyehole.tistory.com/m/999
https://eyehole.tistory.com/999?utm=source
파이썬 코드(title_fetch_urls.py)
*. ROOT_HOST = "본인 블로그 주소URL입력"
import re, time, csv, sys
from pathlib import Path
import requests
from urllib.parse import urlparse, urlunparse
from bs4 import BeautifulSoup
ROOT_HOST = "eyehole.tistory.com"
INPUT_FILE = "ids.txt" # 전체 URL 목록을 줄바꿈으로 저장
OUT_FILE = "titles.csv"
HEADERS = {"User-Agent": "Mozilla/5.0"}
URL 정규화: 스킴 보정, /m/ 제거, 파라미터/프래그먼트 제거, 불필요 경로 제외
def normalize_url(raw: str) -> str | None:
raw = raw.strip()
if not raw:
return None
# 스킴 보정
if raw.startswith("//"):
raw = "https:" + raw
elif not raw.startswith("http://") and not raw.startswith("https://"):
raw = "https://" + raw
try:
u = urlparse(raw)
if not u.netloc:
return None
# 내 사이트만 처리(필요 시 주석 처리)
if ROOT_HOST not in u.netloc:
return None
# /m/ 정리: https://host/m/123 → https://host/123
path = re.sub(r"^/m/+", "/", u.path)
# 파라미터/프래그먼트 제거
clean = u._replace(path=path, params="", query="", fragment="")
url = urlunparse(clean).rstrip("/")
# 태그/검색/아카이브/공지 경로 제외
if re.search(r"/tag/|/search|/archive|/notice", url):
return None
return url
except Exception:
return None
제목 수집
def fetch_title(url: str) -> tuple[str, str]:
try:
r = requests.get(url, headers=HEADERS, timeout=10, allow_redirects=True)
r.raise_for_status()
# 리디렉션 최종 도착지 정규화
final_url = normalize_url(r.url) or url
soup = BeautifulSoup(r.text, "html.parser")
title = (soup.title.string or "").strip() if soup.title else ""
if not title or len(title) < 3:
h = soup.select_one("h1, h2.post-title, .title, .tit_post, .entry-title")
if h:
title = h.get_text(strip=True)
title = re.sub(r"\s+", " ", title).strip() or "[제목 없음]"
return title, final_url
except Exception as e:
return f"[에러] {e.class.name}", url
def main():
p = Path(INPUT_FILE)
if not p.exists():
print(f"{INPUT_FILE} 파일이 없습니다. 전체 URL을 줄바꿈으로 저장해 주세요.")
sys.exit(1)
rows, seen = [], set()
for line in p.read_text(encoding="utf-8").splitlines():
raw = line.strip()
if not raw:
continue
url = normalize_url(raw)
if not url or url in seen:
continue
seen.add(url)
title, canon = fetch_title(url)
rows.append((url, title, canon))
print(f"{url}\t{title}")
time.sleep(0.25) # 서버 배려
with open(OUT_FILE, "w", newline="", encoding="utf-8") as f:
w = csv.writer(f)
w.writerow(["url", "title", "canonical_url"])
w.writerows(rows)
if name == "main":
main()

실행
- python title_fetch_urls.py
- titles.csv 생성(컬럼: url, title, canonical_url)
확장 팁
- 외부 도메인도 처리하려면 ROOT_HOST 검사 줄을 주석 처리하세요.
- 요청 간격(time.sleep) 0.25 → 0.5로 조정해 안정성을 높일 수 있습니다.
- 스킨에 따라 제목 셀렉터(.tit_post, .entry-title 등)를 1~2개 더 추가하면 인식률이 올라갑니다.
---
3) 결과로 무엇을 할 수 있나(실전 활용)
- 카테고리 허브 제작
- titles.csv를 기준으로 블로그 카테고리별 허브 페이지 제작 → 허브 본문에 앵커 문구로 삽입
- 색인 요청 우선순위 선정
- titles.csv에 최근 수정일/서치 콘솔 내보내기(CTR/순위)를 병합해 점수화 → 상위 10~15개만 먼저 URL 검사·색인 요청
- 사이트맵 정제본(sitemap-clean.xml)
- 표준 URL만 모아 정제본을 만들어 서치 콘솔에 추가 제출
- 내부 링크 정비
- 허브 → 대표 글, 대표 글 ↔ 대표 글 양방향 링크 구성
- /m/, 파라미터 링크 전량 표준 URL로 교체
체크리스트
- [ ] 콘솔에서 allow pasting 후 스니펫 실행
- [ ] /m/, 파라미터, /tag/, /search, /archive, /notice 제외 필터 적용
- [ ] ids.txt에는 “전체 URL”만 줄바꿈으로
- [ ] 파이썬 실행 후 titles.csv 샘플 검수(깨진 제목 여부)
---
4) 자주 묻는 질문(FAQ)
Q. 콘솔에서 붙여넣기가 안 됩니다.
A. Console 탭에서 allow pasting 입력 후 Enter → 그다음 코드를 붙여넣으세요. 그래도 안 되면 Console 포커스·한영 입력 상태를 확인하세요.
Q. 페이지를 넘겨도 수집 개수가 늘지 않아요.
A. 동적 로딩/무한 스크롤이면 끝까지 스크롤 후 실행해야 합니다. 페이지네이션이면 각 페이지에서 반복 실행해 결과를 합치세요. 또는 sitemap.xml 기반 수집과 병행하세요.
Q. 숫자 주소가 아닌 슬러그(문자) 주소가 섞여 있어요.
A. 콘솔·파이썬 모두 슬러그를 허용하도록 정규식을 포함했습니다. 누락되면 슬러그 패턴을 넉넉히 유지하세요.
Q. [제목 없음]으로 나오는 경우가 있어요.
A. 스킨별 제목 셀렉터가 다릅니다. 코드의 soup.select_one에 사용하는 클래스(.tit_post, .entry-title 등)를 스킨에 맞게 추가하세요.
Q. 너무 많은 URL을 한 번에 파싱해도 되나요?
A. 서버 배려를 위해 time.sleep(0.25~0.5)로 요청 간격을 유지하세요. 에러가 뜨면 잠시 대기 후 재시도하세요.
---
마무리
관리자 콘솔로 “표준 URL만” 깨끗이 추출하고, 파이썬으로 “전체 URL”을 바로 파싱해 제목을 매핑하면, 허브 제작·색인 가속·사이트맵 정제·내부 링크 개편이 훨씬 수월해집니다.
티스토리 블로그 페이지 스크롤 진행률 프로그레스 바(Progress Bar) 적용
티스토리 블로그에 프로그레스 바(Progress Bar) 적용하기 최근 이웃분들 블로그를 다니다 보니 눈에 띄는 이상한 그래프 게이지가 있습니다. 스크롤을 내리는데 상단에 진행률 같은 막대가 늘어났
eyehole.tistory.com
♥읽어주셔서 감사합니다♥
티스토리 댓글과 공감♥은 로그인이 필요 없습니다.
로그인하시면 구독 가능합니다.
'IT Lab > 코드 크래프트' 카테고리의 다른 글
| 정규표현식, 고수로 가는 길 (고급 기능과 성능 최적화 전략) (1) | 2025.09.19 |
|---|---|
| 정규표현식, 실전 활용 꿀팁 (자주 쓰는 패턴과 응용 사례) (0) | 2025.09.17 |
| 정규표현식, 첫걸음 (개념과 알아야 할 기본 문법) (1) | 2025.09.15 |
| [Wi-Fi] QR Code Generator-무선접속 QR코드 생성 (10) | 2020.12.07 |
| [F5] L4스위치 Log 확인 방법 (13) | 2020.11.26 |
| [Cisco] ACS 인증서버 admin password 변경 방법(CLI) (2) | 2020.10.07 |
| [Cisco] Archive Backup Falure_ %ARCHIVE_CONFIG-4-ARCHIVE_SKIPPED (0) | 2020.06.24 |
| [Cisco] NX-OS Auto Config Backup (EEM) (0) | 2020.04.28 |