使用requests与lxml爬取ISC学校数据时的多层爬取问题求助
ISC英国学校数据爬取:解决多层页面加载错误及完整爬取流程
错误原因
你遇到的MissingSchema: Invalid URL 'h'错误,核心问题是遍历对象写错了:
area_pages = [requests.get(h) for h in areas_40[0]]
areas_40[0]是单个地区链接字符串(比如'http://www.isc.co.uk/schools/england/derbyshire/'),遍历字符串会把它拆成单个字符(第一个字符就是'h'),传给requests.get()自然触发URL格式错误。
修正及完整爬取代码
下面是修正后的完整代码,实现从地区页面深入爬取单个学校数据:
import pandas as pd import requests from lxml import etree import random # 基础配置 parent_domain = "https://www.isc.co.uk" # 改用https,匹配原网站协议 headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" } # 添加请求头,避免被反爬拦截 # 1. 获取英格兰地区列表并随机抽取40个 response = requests.get(f"{parent_domain}/schools/england/", headers=headers) tree = etree.HTML(response.text) # 直接解析响应文本,简化流程 # 提取地区链接 area_links = tree.xpath('//*[@id="maincontent"]/div/div[2]/div[2]/div[1]/ul/li/a/@href') full_area_urls = [f"{parent_domain}{link}" for link in area_links] areas_40 = random.sample(full_area_urls, 40) # 2. 遍历每个地区页面,提取学校链接 school_urls = [] for area_url in areas_40: try: area_response = requests.get(area_url, headers=headers) area_tree = etree.HTML(area_response.text) # 提取学校详情页链接(根据页面结构调整xpath,这里匹配常见的学校卡片链接) school_links = area_tree.xpath('//div[contains(@class, "school-card")]/a/@href') for link in school_links: # 兼容相对链接和绝对链接 if link.startswith("http"): school_urls.append(link) else: school_urls.append(f"{parent_domain}{link}") except Exception as e: print(f"处理地区页面 {area_url} 出错: {e}") continue # 3. 遍历学校链接,爬取单个学校数据 school_data = [] for school_url in school_urls: try: school_response = requests.get(school_url, headers=headers) school_tree = etree.HTML(school_response.text) # 提取学校核心信息(示例字段,可根据页面实际结构调整xpath) school_info = { "学校名称": school_tree.xpath('//h1/text()')[0].strip() if school_tree.xpath('//h1/text()') else None, "学校地址": school_tree.xpath('//div[contains(@class, "address")]/text()')[0].strip() if school_tree.xpath('//div[contains(@class, "address")]/text()') else None, "官方网站": school_tree.xpath('//a[contains(text(), "Visit website")]/@href')[0] if school_tree.xpath('//a[contains(text(), "Visit website")]/@href') else None, "ISC页面链接": school_url } school_data.append(school_info) except Exception as e: print(f"处理学校页面 {school_url} 出错: {e}") continue # 4. 保存数据到CSV df = pd.DataFrame(school_data) df.to_csv("英国ISC学校数据.csv", index=False, encoding="utf-8-sig") print("数据爬取完成,已保存到英国ISC学校数据.csv")
关键优化点
- 修正遍历对象:将
areas_40[0]改为areas_40,确保遍历的是40个地区链接而非单个字符串的字符 - 简化解析流程:用
etree.HTML()替代etree.parse(StringIO(str(f.content))),直接处理响应文本 - 防反爬处理:添加
User-Agent请求头,降低被网站拦截的概率 - 异常容错:增加异常捕获,避免单个页面出错导致整个爬取流程中断
- 链接兼容性:自动处理相对链接和绝对链接,确保学校链接格式正确
内容的提问来源于stack exchange,提问作者elksie5000
相关产品推荐
相关产品推荐

