基于页面位置提取网站URL分组异常问题求助
解决URL按页面位置分组的问题
问题根源在于你靠URL关键词判断位置的思路完全行不通——页面页眉、页脚这些区域的链接没有固定的关键词特征,必须通过HTML元素的DOM结构(比如<header>、<footer>、<aside>这类标准标签,或者网站自定义的类名)来定位区域,再提取对应区域里的链接。
下面是修正后的代码,以numpy官网为例,通过定位页面的标准结构标签来分组URL:
import requests from bs4 import BeautifulSoup from urllib.parse import urljoin def extract_urls_by_section(url): # 初始化分组字典 url_groups = { "页眉": [], "正文": [], "侧边栏": [], "页脚": [] } # 获取页面内容 response = requests.get(url) soup = BeautifulSoup(response.text, 'html.parser') # 1. 提取页眉区域的URL(通常对应<header>标签) header = soup.find('header') if header: header_links = header.find_all('a', href=True) for link in header_links: href = link['href'] # 转成绝对URL,过滤无效链接(锚点、javascript跳转等) absolute_url = urljoin(url, href) if not absolute_url.startswith(('javascript:', '#', 'mailto:')): url_groups["页眉"].append(absolute_url) # 2. 提取页脚区域的URL(通常对应<footer>标签) footer = soup.find('footer') if footer: footer_links = footer.find_all('a', href=True) for link in footer_links: href = link['href'] absolute_url = urljoin(url, href) if not absolute_url.startswith(('javascript:', '#', 'mailto:')): url_groups["页脚"].append(absolute_url) # 3. 提取侧边栏区域的URL(numpy官网侧边栏用<aside>标签) sidebar = soup.find('aside') if sidebar: sidebar_links = sidebar.find_all('a', href=True) for link in sidebar_links: href = link['href'] absolute_url = urljoin(url, href) if not absolute_url.startswith(('javascript:', '#', 'mailto:')): url_groups["侧边栏"].append(absolute_url) # 4. 提取正文区域的URL(排除页眉、页脚、侧边栏后的内容,通常对应<main>标签) main_content = soup.find('main') if main_content: # 移除main里可能包含的其他区域元素,避免重复提取 for section in [header, footer, sidebar]: if section and section.parent == main_content: section.decompose() main_links = main_content.find_all('a', href=True) for link in main_links: href = link['href'] absolute_url = urljoin(url, href) if not absolute_url.startswith(('javascript:', '#', 'mailto:')): # 确保链接未被分到其他组 if absolute_url not in url_groups["页眉"] and absolute_url not in url_groups["页脚"] and absolute_url not in url_groups["侧边栏"]: url_groups["正文"].append(absolute_url) # 给每个分组去重 for key in url_groups: url_groups[key] = list(set(url_groups[key])) return url_groups # 测试numpy官网 if __name__ == "__main__": numpy_url = "https://numpy.org/" result = extract_urls_by_section(numpy_url) for section, urls in result.items(): print(f"\n--- {section} URL ---") for url in urls: print(url)
关键说明:
- 核心逻辑是通过HTML结构标签定位区域:用
<header>抓页眉,<footer>抓页脚,<aside>抓侧边栏,<main>抓正文,这是大部分现代网站的标准结构。 - 处理相对URL转绝对URL:用
urljoin把页面里的相对路径(比如/install)转成完整URL,避免提取到无效的路径。 - 过滤无效链接:排除锚点、javascript跳转、邮件链接这类非目标URL。
- 去重处理:避免同一链接在多个区域重复出现(比如有些链接可能同时出现在页眉和页脚)。
运行这段代码后,你会发现/install、/learn这类原本属于页眉的链接会被正确分到“页眉”分组里,页脚的链接也会被正常提取,不会再出现分组为空的情况。
内容的提问来源于stack exchange,提问作者gerryjonez
相关产品推荐
相关产品推荐

