2023 年 4 月 10 日,2023 年河北省普通高等职业教育单独考试招生计划 出来了,但是看到下面满屏的下载地址,纠结了,该怎么一键存储到本地呢?
该爬虫工程师上场了。
页面 、 案例分析
本地要采集的目标数据非常简单,是一些公开的单招计划,每次点击之后都可以打开对应的 PDF 文件。
查看源码也可以直接获取到对应的 PDF 地址。
<a
href="http://file.hebeea.edu.cn/files/article/2023/04/20230409155430_867.pdf"
title="统考单招计划 考试一类.pdf"
target="_blank"
>统考单招计划 考试一类.pdf</a
>
基于这些信息,就可以整理本次爬虫案例的思路了。
- 采集页面中的
.att_content
表格中的所有超链接; - 下载 PDF 文件,并保存为中文名称。
爬虫库选择
基于本案例的难易程度,我们采用 requests 模块配合 lxml 模块进行数据采集。
代码编写
import requests
from lxml import etree
def download_file(file_name, file_path):
res = requests.get(file_path, headers=headers)
file_content = res.content
with open(f'./danzhao/{file_name}', 'wb') as f:
f.write(file_content)
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36"
}
res = requests.get("http://www.hebeea.edu.cn/html/zkyj/2023/0409-160117-994.html", headers=headers)
res.encoding = "utf-8"
elementes = etree.HTML(res.text)
li_list = elementes.xpath(".//table[@class='att_content']//li")
for item in li_list:
file_name = item.xpath("./a/text()")[0] # 文件名
file_path = item.xpath("./a/@href")[0] # 文件下载路径
download_file(file_name, file_path)
可以看到代码中没有高级语法,仅采用简单的逻辑即可实现对 单招招生计划的一键下载。
补充一下语法说明
为了便于大家学习,这里再补充一下相关的语法说明。
使用 XPath 语法选择元素
使用 XPath 语法可以选择 XML 文档中的特定元素。可以使用以下代码进行选择:
# 选择根元素
root = tree.xpath('/')
# 选择所有元素
elements = tree.xpath('//*')
# 选择具有特定标签的元素
tagged_elements = tree.xpath('//tagname')
# 选择具有特定属性的元素
attributed_elements = tree.xpath('//*[@attribute="value"]')
# 选择具有特定文本内容的元素
text_elements = tree.xpath('//text()[contains(.,"search_text")]')
获取元素信息
选择元素后,可以使用以下方法获取它们的信息:
# 获取元素标签
element.tag
# 获取元素属性
element.attrib
# 获取元素文本内容
element.text
XPath 的其他注意事项
- 路径可以是绝对或相对的。使用绝对路径时,必须从根元素开始。使用相对路径时,可以从当前元素或任何祖先元素开始。
- 在路径中使用谓词来进一步筛选元素。可以使用
[@attribute='value']
来选择具有特定属性值的元素。 - 使用多个谓词来进一步筛选元素。可以使用
[@attribute1='value1'][@attribute2='value2']
来选择具有多个属性值的元素。 - 使用通配符
*
来选择所有元素,或者使用.
来选择当前元素。可以使用..
来选择父元素。 - 使用
text()
函数来选择文本节点。可以使用//text()
来选择文档中的所有文本节点。 - 使用
contains()
函数来查找包含特定文本的元素。可以使用//element[contains(text(),'search_text')]
来选择包含特定文本的元素。