如何爬取整站域名下所有PDF链接 修复BeautifulSoup爬虫现有缺陷
问题根因
现有代码的核心错误有3个:
- 提取域名的逻辑硬编码了
.com后缀,而你要爬的站点是.de后缀,导致域名提取完全错误,内链外链判断逻辑完全失效 - 没有做相对路径转绝对路径的处理,所有相对路径的链接都会被误判
- 仅爬取了首页一个页面,没有递归遍历全站所有内链
实现方案
不需要引入额外复杂库,用Python标准库urllib.parse配合requests+BeautifulSoup即可实现,核心需要新增两个逻辑:相对路径转绝对路径、全站广度优先遍历+去重。
修改后完整代码
import requests from bs4 import BeautifulSoup from urllib.parse import urljoin, urlparse from collections import deque if __name__ == '__main__': # 配置参数 base_url = "https://www.aurednik.de/" parsed_base = urlparse(base_url) base_domain = parsed_base.netloc # 自动提取域名,无需硬编码后缀 # 待爬队列、已爬集合、PDF链接集合 to_crawl = deque([base_url]) crawled = set() pdf_links = set() # 请求头避免被站点反爬拦截 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36" } while to_crawl: current_url = to_crawl.popleft() if current_url in crawled: continue # 标记为已爬 crawled.add(current_url) print(f"正在爬取: {current_url}") try: resp = requests.get(current_url, headers=headers, timeout=10) resp.raise_for_status() # 非HTML内容跳过解析 if 'text/html' not in resp.headers.get('Content-Type', ''): # 直接判断是否为PDF if current_url.lower().endswith('.pdf'): pdf_links.add(current_url) continue except Exception as e: print(f"爬取失败 {current_url}: {str(e)}") continue soup = BeautifulSoup(resp.text, 'lxml') for a_tag in soup.find_all('a', href=True): href = a_tag['href'].strip() # 转成绝对路径 abs_href = urljoin(current_url, href) # 去掉锚点避免重复爬取同一页面 abs_href = abs_href.split('#')[0] parsed_href = urlparse(abs_href) # 筛选同域名内链 if parsed_href.netloc == base_domain: # 先判断是不是PDF if abs_href.lower().endswith('.pdf'): pdf_links.add(abs_href) # 不是PDF且没爬过的加入待爬队列 elif abs_href not in crawled and abs_href not in to_crawl: to_crawl.append(abs_href) # 输出结果 print("\n=== 所有PDF链接 ===") for pdf in pdf_links: print(pdf)
代码说明
- 用
urlparse自动提取站点域名,兼容所有后缀的域名,不会出现硬编码.com的错误 - 用
urljoin自动把相对路径拼接成绝对路径,避免路径判断错误 - 用广度优先遍历+去重逻辑遍历全站所有内链,不会漏爬页面
- 对每个链接先判断是不是PDF后缀,是就直接存入结果,不是的同域名内链加入爬取队列
- 加了UA请求头避免被站点反爬拦截,加了超时和异常处理避免爬取中断
内容的提问来源于stack exchange,提问作者x89
相关产品推荐
相关产品推荐

