通过python爬虫在四川大学官网获取四川大学2018-2019各省市各专业录取分数线。
由于官网信息中,2015-2017的数据是存放在一个页面,而2018、2019的数据都是单独的页面,相对规律一些,所以我们今天就来获取2018-2019的信息。
0X00、准备工作
安装标准库lxml、requests、re、requests.exceptions、os和openpyxl。
0X01、页面分析
首先进去是这样的页面:
标题2018年各省(市、区)分专业录取情况统计表(理工)是这样的:
而各个省市的名字和链接则是这样:
弄清楚后比较简单了。
首先还是第一个函数get_page,传入页面url作为参数,获取相应内容,要更改编码为‘utf-8’,不然之后会出现乱码的情况。
def get_page(url):
try:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"}
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
if response.status_code == 200:
return response.text
else:
return None
except RequestException:
return None
然后就是第二个函数get_link,获取每个主页面下的所有省市的名字和链接。
首先通过xpathtitle = text.xpath('//form[@name="_newscontent_fromname"]/h2/text()')
获取当前页面的标题,然后通过正则表达式得到当前页面所属的年份与类别(理工,文史),以备后续使用。
通过之前获取的信息,得到我们存放所有链接的文件的名字,如果文件不存在则新建文件。
吸取了昨天的教训,好好看了一下xpath,
link_content = text.xpath('//td/p/a/@href')
province_content = text.xpath('//td/p/a/text()')
拿到所有的链接和名字,将其存入文件中。注意这里获得的链接是 相对路径,加上前面的内容补充为完整链接。
def get_link(text):
text = etree.HTML(text)
# xpath获取页面标题"201x年各省(市、区)分专业录取情况统计表(xx)"
title = text.xpath('//form[@name="_newscontent_fromname"]/h2/text()')
title_content = re.findall('(\\d*)年各省\\(市、区\\)分专业录取情况统计表((.{2}))', title[0], flags=0)
# 获取当前页面所属的年份与类别(理工,文史)
year = str(title_content[0][0])
data_type = str(title_content[0][1])
# 打开文件
file_name = year + '(' + data_type + ')' + '各省市链接.xlsx'
if os.path.exists(file_name):
print('文件' + file_name + '已存在!')
wb = openpyxl.load_workbook(file_name)
print('文件' + file_name + '打开成功!')
else:
wb = openpyxl.Workbook() # 创建文件对象
print('文件' + file_name + '创建成功!')
ws = wb.active
ws['A1'] = '年份'
ws['B1'] = '类别'
ws['C1'] = '省份'
ws['D1'] = '链接'
# 下一次填入数据的行数
index = 2
link_content = text.xpath('//td/p/a/@href')
province_content = text.xpath('//td/p/a/text()')
for i in range(len(link_content)):
ws.cell(index, 1, year)
ws.cell(index, 2, data_type)
ws.cell(index, 3, province_content[i])
link = 'http://zs.scu.edu.cn/info' + link_content[i].strip('..')
ws.cell(index, 4, link)
print(year + '年' + province_content[i] + '普通类录取分数线统计表(' + data_type + ')链接写入成功!')
index += 1
print(year + '年所有省市普通类录取分数线统计表(' + data_type + ')链接写入完成!')
wb.save(filename=file_name)
拿到每个省市信息的链接后,下一步来分析信息页面:
页面标题和之前的一样,只是注意一下用xpath的时候form标签的name属性值变了,其他的和上一个页面一样。
而下面的专业数据则是在td标签下的span标签中(要注意一下19年理工的页面没有这个span标签,所以代码要做一下判断是不是19年理工)
下面就是得到页面数据的函数parse_one_page,传入url参数,还是先获取页面标题,正则表达式获取页面所属的年份、省份与类别(理工,文史)。
下面的操作和之前差不多。
然后这里判断一下是不是19年理工,选择不同的xpath表达式,然后将其写入文档。
通过判断列数是不是等于6,等于6的话则该专业数据填写完毕,转到下一行。保存文件即可。
def parse_one_page(data_url):
data_text = get_page(data_url)
data_text = etree.HTML(data_text)
title = data_text.xpath('//form[@name="_newscontent_fromname"]/h2/text()')
title_content = re.findall('(\\d*)年(.*?)普通类录取分数线统计表\\((.{3})\\)', title[0], flags=0)
# 获取当前页面所属的年份、省份与类别(理工,文史)
year = str(title_content[0][0])
province = str(title_content[0][1])
data_type = str(title_content[0][2])
# 打开文件
file_name = year + '(' + data_type + ')/' + year + '(' + data_type + ')' + province + '各专业录取分数.xlsx'
folder_name = year + '(' + data_type + ')'
if not os.path.exists(folder_name): # 如果路径不存在
os.makedirs(folder_name)
if os.path.exists(file_name):
print(file_name + '已存在!')
return None
else:
wb = openpyxl.Workbook() # 创建文件对象
print('文件' + file_name + '创建成功!')
ws = wb.active
ws['A1'] = '专业名称'
ws['B1'] = '最高分'
ws['C1'] = '最低分'
ws['D1'] = '平均分'
ws['E1'] = '录取人数'
index = 2
columns = 1
if (year == 2019) & (data_type == '理工'):
content = data_text.xpath('//tbody/tr/td/text()')
else:
content = data_text.xpath('//tbody/tr/td/span/text()')
for i in range(5, len(content)):
ws.cell(index, columns, content[i])
columns += 1
if columns == 6:
index += 1
columns = 1
print(file_name + '写入完毕')
wb.save(filename=file_name)
接下来就是函数send_links,将之前保存在文档中的链接逐个读取,传入函数parse_one_page,以此获取每个省份数据。
def send_links():
year = input('请输入要获取数据的年份:')
type = input('请输入要获取数据的类别(理工/文史):')
file_name = year + '(' + type + ')各省市链接.xlsx'
try:
wb = openpyxl.load_workbook(file_name)
ws = wb.active
a = 'a'
i = 2
while a != '':
a = ws.cell(i, 4).value
if a is not None:
parse_one_page(a)
i += 1
else:
print(year + '(' + type + ')数据获取完毕')
return
except FileNotFoundError:
print('不存在输入信息的文件,请检查输入!')
0X03、完整代码
import requests
from requests.exceptions import RequestException
from lxml import etree
import re
import os
import openpyxl
def get_page(url):
try:
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:77.0) Gecko/20100101 Firefox/77.0"}
response = requests.get(url, headers=headers)
response.encoding = 'utf-8'
if response.status_code == 200:
return response.text
else:
return None
except RequestException:
return None
def get_link(text):
text = etree.HTML(text)
# xpath获取页面标题"201x年各省(市、区)分专业录取情况统计表(xx)"
title = text.xpath('//form[@name="_newscontent_fromname"]/h2/text()')
title_content = re.findall('(\\d*)年各省\\(市、区\\)分专业录取情况统计表((.{2}))', title[0], flags=0)
# 获取当前页面所属的年份与类别(理工,文史)
year = str(title_content[0][0])
data_type = str(title_content[0][1])
# 打开文件
file_name = year + '(' + data_type + ')' + '各省市链接.xlsx'
if os.path.exists(file_name):
print('文件' + file_name + '已存在!')
wb = openpyxl.load_workbook(file_name)
print('文件' + file_name + '打开成功!')
else:
wb = openpyxl.Workbook() # 创建文件对象
print('文件' + file_name + '创建成功!')
ws = wb.active
ws['A1'] = '年份'
ws['B1'] = '类别'
ws['C1'] = '省份'
ws['D1'] = '链接'
index = 2
link_content = text.xpath('//td/p/a/@href')
province_content = text.xpath('//td/p/a/text()')
for i in range(len(link_content)):
ws.cell(index, 1, year)
ws.cell(index, 2, data_type)
ws.cell(index, 3, province_content[i])
link = 'http://zs.scu.edu.cn/info' + link_content[i].strip('..')
ws.cell(index, 4, link)
print(year + '年' + province_content[i] + '普通类录取分数线统计表(' + data_type + ')链接写入成功!')
index += 1
print(year + '年所有省市普通类录取分数线统计表(' + data_type + ')链接写入完成!')
wb.save(filename=file_name)
def parse_one_page(data_url):
data_text = get_page(data_url)
data_text = etree.HTML(data_text)
title = data_text.xpath('//form[@name="_newscontent_fromname"]/h2/text()')
title_content = re.findall('(\\d*)年(.*?)普通类录取分数线统计表\\((.{3})\\)', title[0], flags=0)
# 获取当前页面所属的年份、省份与类别(理工,文史)
year = str(title_content[0][0])
province = str(title_content[0][1])
data_type = str(title_content[0][2])
# 打开文件
file_name = year + '(' + data_type + ')/' + year + '(' + data_type + ')' + province + '各专业录取分数.xlsx'
folder_name = year + '(' + data_type + ')'
if not os.path.exists(folder_name): # 如果路径不存在
os.makedirs(folder_name)
if os.path.exists(file_name):
print(file_name + '已存在!')
return None
else:
wb = openpyxl.Workbook() # 创建文件对象
print('文件' + file_name + '创建成功!')
ws = wb.active
ws['A1'] = '专业名称'
ws['B1'] = '最高分'
ws['C1'] = '最低分'
ws['D1'] = '平均分'
ws['E1'] = '录取人数'
index = 2
columns = 1
if (year == 2019) & (data_type == '理工'):
content = data_text.xpath('//tbody/tr/td/text()')
else:
content = data_text.xpath('//tbody/tr/td/span/text()')
for i in range(5, len(content)):
ws.cell(index, columns, content[i])
columns += 1
if columns == 6:
index += 1
columns = 1
print(file_name + '写入完毕')
wb.save(filename=file_name)
def send_links():
year = input('请输入要获取数据的年份:')
type = input('请输入要获取数据的类别(理工/文史):')
file_name = year + '(' + type + ')各省市链接.xlsx'
try:
wb = openpyxl.load_workbook(file_name)
ws = wb.active
a = 'a'
i = 2
while a != '':
a = ws.cell(i, 4).value
if a is not None:
parse_one_page(a)
i += 1
else:
print(year + '(' + type + ')数据获取完毕')
return
except FileNotFoundError:
print('不存在输入信息的文件,请检查输入!')
url = {'2019理工': 'http://zs.scu.edu.cn/info/1037/2083.htm',
'2019文史': 'http://zs.scu.edu.cn/info/1037/2128.htm',
'2018理工': 'http://zs.scu.edu.cn/info/1037/1370.htm',
'2018文史': 'http://zs.scu.edu.cn/info/1037/1489.htm', }
choice = input('请输入想获取的年份与类别各省份总链接(2018理工、2018文史、2019理工、2019文史):')
try:
text = get_page(url[choice])
if text is not None:
get_link(text)
send_links()
except KeyError:
print('输入有误,请检查输入!')
0X04、反思
其实回过头来看代码还是比较简单的,但是还是花了很多时间(害),19理工和其他页面不同这,排查了半天才注意到,细心程度有待提高。
还有新建文件夹,在文件夹下新建文件这,也搞错了好几次。
一天比一天进步一点,加油!