别再硬记XPath语法了!用Python+lxml实战爬取豆果美食,手把手教你写循环抓取菜谱
2026/6/13 15:06:54 网站建设 项目流程

用Python+lxml实战解析豆果美食:从XPath零基础到循环抓取菜谱

每次看到美食网站上的诱人菜谱,你有没有想过如何批量获取这些数据?今天我们就用Python的lxml库,通过XPath语法从豆果美食抓取菜谱信息。不同于枯燥的语法记忆,我们将通过真实案例带你理解XPath的核心用法。

1. 环境准备与基础概念

在开始之前,确保你已经安装了必要的Python库。打开终端运行以下命令:

pip install requests lxml tabulate

这三个库各司其职:

  • requests:用于获取网页HTML内容
  • lxml:提供XPath解析功能
  • tabulate:美化数据输出格式

XPath本质是一种在HTML/XML文档中导航和查询节点的语言。想象它就像文件系统的路径:

  • /html/body类似于C:/Users/Documents
  • //div则像全局搜索所有文件夹中的div文件
from lxml import etree import requests url = 'https://www.douguo.com/' response = requests.get(url) html = etree.HTML(response.text) # 将HTML转换为XPath可解析的对象

2. XPath核心语法实战解析

2.1 基础定位技巧

观察豆果美食首页的HTML结构,菜谱信息通常包含在特定CSS选择器的元素中。通过浏览器开发者工具(F12),我们可以看到菜谱区块的结构特征。

常用定位方式对比

表达式说明示例
/从根节点开始的绝对路径/html/body/div
//文档任意位置的相对路径//div[@class="recipe"]
@属性定位//a[@href]
[]谓语条件(相当于筛选条件)//li[1](第一个li元素)
# 获取第一个菜谱名称 first_recipe = html.xpath('//*[@id="content"]/ul[1]/li[1]/div/a/text()')[0] print(f"首个菜谱:{first_recipe}")

2.2 动态路径与循环抓取

当我们需要获取多个相似结构的元素时,手动逐个定位效率极低。通过分析DOM结构,发现菜谱列表的<li>标签序号是连续变化的:

for i in range(1, 9): name = html.xpath(f'//*[@id="content"]/ul[1]/li[{i}]/div/a/text()') author = html.xpath(f'//*[@id="content"]/ul[1]/li[{i}]/div/p/a[1]/text()') print(f"{name[0]} - 作者:{author[0]}")

循环优化技巧

  1. 使用string()函数避免空值:xpath('string(//div)')
  2. |合并多个路径:xpath('//h1|//h2')
  3. 通过contains()模糊匹配:xpath('//div[contains(@class,"recipe")]')

3. 数据清洗与结构化输出

原始抓取的数据往往需要进一步处理。我们使用tabulate库将结果格式化为美观的表格:

from tabulate import tabulate data = [] for i in range(1, 9): row = [ html.xpath(f'//*[@id="content"]/ul[1]/li[{i}]/div/a/text()')[0], html.xpath(f'//*[@id="content"]/ul[1]/li[{i}]/div/p/a[1]/text()')[0] ] data.append(row) print(tabulate(data, headers=['菜谱名称', '作者'], tablefmt='grid'))

输出示例:

+----------------------------+----------+ | 菜谱名称 | 作者 | +============================+==========+ | 红烧肉 | 厨神老王 | | 清蒸鲈鱼 | 美食小李 | +----------------------------+----------+

4. 异常处理与反爬应对

真实项目中总会遇到各种意外情况。以下是几个关键防护措施:

try: response = requests.get(url, headers={ 'User-Agent': 'Mozilla/5.0', 'Accept-Language': 'zh-CN' }, timeout=5) response.raise_for_status() html = etree.HTML(response.text) # 添加数据存在性检查 recipes = html.xpath('//*[@id="content"]/ul[1]/li') if not recipes: print("警告:未找到菜谱数据,可能页面结构已变更") except requests.exceptions.RequestException as e: print(f"网络请求失败:{str(e)}")

反爬策略备忘单

  • 随机延迟:time.sleep(random.uniform(1,3))
  • 代理IP轮换
  • 模拟真实浏览器头部信息
  • 检查response.status_code

5. 项目扩展与进阶技巧

掌握了基础抓取后,可以尝试以下扩展方向:

  1. 多页爬取:分析分页规律,如?page=2参数
  2. 详情页抓取:提取每个菜谱的详细做法和食材
  3. 数据存储:使用SQLite或MongoDB持久化数据
  4. 定时任务:结合APScheduler实现每日自动更新
# 示例:获取菜谱详情URL detail_urls = html.xpath('//*[@id="content"]/ul[1]/li/div/a/@href') for url in detail_urls: full_url = f"https://www.douguo.com{url}" detail_page = requests.get(full_url).text # 解析详情页内容...

记住,实际开发中要遵守网站的robots.txt规则,控制请求频率。当遇到动态加载内容时,可能需要使用Selenium等工具配合XPath使用。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询