首先简介:
人话来说就是通过Xpath代码爬取网页里面我们想要的信息,比如小编这里就是爬取了星座运势,星座日期,星座运势;大家可以用来提取网页数据,比如球队信息,高考录取全部信息等等,这里不介绍,下面上干货
上干货之前
对于一些网站,大规模爬取或大规模频繁请求时,网站可能会出现以下情况: 弹出验证码; 跳到登录认证页面; 直接封禁客户端的IP,一段时间内无法访问;
或者直接换网就行
通过代理设置可以解决上述问题,代理服务器(Proxy Server)的功能是代理网络用户去取得网络信息。形象地说,它是网络信息的中转站,是个人网络和Internet服务商之间的中间代理机构,负责转发合法的网络信息,对转发进行控制和登记。
大头之Requests 库:爬虫开发的利器
Requests 库作为 Python 中处理 HTTP 请求的优秀第三方库,不仅能实现基本的网络请求,其高级功能更能应对复杂的爬虫场景,提升爬取效率与稳定性。
会话简介
在 Web 开发中,会话(Session)是维护用户状态的关键机制。服务器通过会话对象存储用户数据,以便在用户后续操作中提供个性化服务。Requests 库的 session 对象完美模拟了这一过程,能自动处理 Cookies,轻松实现会话保持。
其核心优势在于:一次登录后,后续请求无需重复提交身份信息,只需通过 session 对象发起请求即可携带必要的 Cookies 信息。例如,在登录 QQ 邮箱时,通过 session.post () 方法提交账号密码后,后续的邮件访问请求可直接使用该 session 对象,无需再次验证,极大简化了需要身份认证的爬虫开发。
session 对象提供了丰富的方法,包括 get ()、post () 用于发起请求,cookies () 获取 Cookies 信息,headers () 查看请求头等,满足会话管理的各种需求。
对战代码
XPath:精准解析网页数据
获取网页内容后,高效解析数据是爬虫开发的另一关键环节。XPath 作为一门在 XML/HTML 文档中查找信息的语言,凭借其强大的路径表达式,成为数据解析的首选工具。
XPath 基本语法与规则
XPath 通过路径表达式选取文档中的节点,常用规则包括:
- 斜杠(/)表示从根节点选取,双斜杠(//)表示从任意位置选取节点;
- 点(.)代表当前节点,双点(..)代表父节点;
- @符号用于选取属性,如 //@href 可获取所有 href 属性值。
谓语(Predicates)用于筛选特定节点,如 /bookstore/book [1] 选取第一个 book 节点,//title [@lang='eng'] 选取 lang 属性为 eng 的 title 节点。通配符(、@、node ())可匹配未知元素,“|” 运算符则支持同时选取多个路径,极大增强了节点选取的灵活性。
lxml 库:XPath 解析的强力支撑
Python 的 lxml 库提供了 etree 模块,专为 XML/HTML 解析设计,与 XPath 配合使用能高效提取数据。etree.HTML () 方法可将 HTML 字符串转换为可解析的 Element 对象,并自动补全不完整的标签,确保解析准确性;parse () 方法用于解析本地文件;tostring () 方法则能将 Element 对象转回字符串形式。
在实际应用中,通过 XPath 表达式与 etree 方法结合,可轻松完成各种解析任务:
- 选取子节点或子孙节点://li/a
- 获取父节点属性://a [@href="link4.html"]/../@class
- 过滤特定属性的节点://li [@class="item-1"]
- 提取文本内容://li [@class="item-1"]/a/text ()
- 获取属性值://li/a/@href
import requests from lxml import etree import csv def get_html(url, timeout=30): """获取网页内容""" try: headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36" } r = requests.get(url, timeout=timeout, headers=headers) r.raise_for_status() # 检查请求是否成功 r.encoding = "utf-8" # 手动指定编码 return r.text except Exception as error: print(f"网页内容获取失败: {error}") return None def parse(html): """解析网页,提取星座名称、日期和运势概述""" if not html: return [] doc = etree.HTML(html) out_list = [] # 1. 修正XPath错误:移除末尾多余的"]",并准确定位星座容器 constellations = doc.xpath('//*[@id="list"]/div[1]/div/dl/dd') # 去掉末尾多余的"]" for item in constellations: try: # 2. 提取文本必须用text(),否则获取的是元素对象(导致strip()错误) # 使用相对路径"./"从当前item节点开始查找,避免全局重复提取 name = item.xpath('./strong/text()')[0].strip() # 星座名 date = item.xpath('./small/text()')[0].strip() # 对应日期 overview = item.xpath('./p/text()')[0].strip() # 运势概述 out_list.append([name, date, overview]) print(f"已提取: {name} ({date})") except IndexError: print("部分信息缺失,跳过该星座") continue except Exception as e: print(f"解析出错: {e}") continue return out_list def save_csv(items, path): """保存数据到CSV文件""" if not items: print("没有数据可保存") return # 3. 修正文件格式:将.text改为.csv(符合CSV格式) with open(path, 'w', newline='', encoding='utf-8-sig') as f: csv_writer = csv.writer(f) csv_writer.writerow(['星座名字', '对应日期', '运势概述']) # 表头 csv_writer.writerows(items) # 写入数据 print(f"数据已保存到 {path}") if __name__ == "__main__": url = "https://www.xzw.com/fortune/" html = get_html(url) if html: constellation_list = parse(html) # 4. 修正文件后缀为.csv save_csv(constellation_list, '星座信息.csv')