和青山 奏江河
我知青山江河乐
抚琴为人 无人知我乐
“洋洋兮又复巍峨”
来客忽笑我
声声所念 来人皆可得
徒余留 明月忆往昔
温酒会知音
借问人间 知我者能有几
三尺瑶琴碎骨兮
似绝弦断悲心
孑然一身 苍茫天地兮
🎵 国风堂、哦漏《知我》
使用 Requests 与 lxml 实现 Foooooot 旅游列表爬取
本文演示如何用
requests
+lxml
从foooooot.com
抓取旅行线路列表,涵盖请求封装、页面解析、数据抽取等步骤。
一、项目背景
Foooooot 是一个分享各地旅行、徒步、自驾等线路的网站。在无法使用 Scrapy 时,我们也可以借助轻量级的 requests
+ lxml
组合,实现同样的列表页爬取功能。
二、环境准备
- Python 3.7+
- 安装依赖:
pip install requests lxml
三、核心代码
# -*- coding:utf-8 -*-
import re
import requests
from lxml import etree
# 全局 headers 和 cookies
HEADERS = {
'User-Agent': (
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) '
'AppleWebKit/537.36 (KHTML, like Gecko) '
'Chrome/126.0.0.0 Safari/537.36'
),
}
COOKIES = {
"csrftoken": "cookie 信息",
"sessionid": "cookie 信息"
}
def fetch(url: str) -> etree._Element:
"""
用 requests 获取页面并返回解析后的 etree 对象
"""
resp = requests.get(url, headers=HEADERS, cookies=COOKIES, timeout=10)
resp.raise_for_status()
return etree.HTML(resp.text)
def parse_list(tree: etree._Element) -> list:
"""
解析列表页节点,返回一个包含所有线路信息的 dict 列表
"""
items = []
nodes = tree.xpath("//div[@class='listSection']/ul[@class='tripsList']/li")[1:-1]
for node in nodes:
title = "".join(node.xpath(".//p[@class='trip-title']/a//text()")).strip()
url = node.xpath(".//p[@class='trip-title']/a/@href")[0]
unstr = "".join(node.xpath(".//td[1]/div/dl/dd//text()")).strip()
code = url.split("/")[-2]
date_str = re.findall(r"\d{4}-\d+-\d+", unstr)[0]
addr = "".join(node.xpath(".//tr[1]/td[1]/div/dl/dd[3]//text()")).split(":")
address_src, address_des = addr[0].strip(), addr[-1].strip()
items.append({
"title": title,
"url": url,
"dateStr": date_str,
"code": code,
"addressSrc": address_src,
"addressDes": address_des,
"flag": 0,
})
return items
def main():
# 单页测试 URL(以“天安门”为关键词)
url = (
"http://www.foooooot.com/search/trip/all/432/"
"all/weight/descent/?keyword=%E5%A4%A9%E5%AE%89%E9%97%A8"
)
tree = fetch(url)
for item in parse_list(tree):
print(item)
if __name__ == '__main__':
main()
四、代码解析
- 请求封装(fetch)
- 使用 requests.get 发起 HTTP GET 请求,带上自定义 HEADERS 和 COOKIES,模拟浏览器行为。
- resp.raise_for_status() 确保非 200 响应会抛出异常。
- HTML 解析 (lxml.etree)
- etree.HTML(resp.text) 将响应内容解析为可执行 XPath 操作的树形结构。
- 列表数据抽取 (parse_list)
- //div[@class=‘listSection’]/ul/li 定位所有条目节点,跳过第一和最后一个非数据节点。
- 利用 .xpath() 提取标题、链接、日期等字段,并通过正则 \d{4}-\d±\d+ 拆出日期。
- 经过清洗后,将每条记录组装成 dict,方便后续处理或入库。
- 运行流程 (main)
- 构造测试 URL,调用 fetch 和 parse_list,最后打印所有抓取到的条目。
五、扩展与优化
- 多页循环:将主流程改为 while next_page_url,实现自动翻页。
- 动态代理:在 requests.get 中加入 proxies 参数,避免 IP 限制。
- 结果存储:可将 items 写入文件、数据库或消息队列。
- 异常处理:在网络不稳定或解析失败时,加重试机制与日志。
总结
通过 requests + lxml,我们可以快速搭建一个轻量化的爬虫脚本,适用于简单列表页的抓取需求。核心思路包括请求封装、XPath 抽取、正则清洗以及循环控制。后续如需更完善的管道、调度与去重,可考虑使用 Scrapy 或其他爬虫框架,但数据解析部分的思路基本一致。