飞道的博客

爬虫百战穿山甲(4):帮学弟学妹们看看高考选科走班指南

200人阅读  评论(0)

郑重申明:本文仅为研究学习使用


网页分析

网址:http://wjt.a.101.com/activity/2020/gaokaotool/search-km.shtml

目前是有八个省的数据,但是其他几个省的数据都有Excel直接下载了,所以就选择福建的啦。
能简单就简单嘛。

可以看到页面中有两个下拉框和一个“开始查询”按钮,且让我们点击一下查询按钮看情况。

点击之后发现,依旧是一个动态网页。

所以我们熟练地点开网络抓包工具:
就一个包,没什么好说的,点开看:

url:
https://wjt-subject-tool-api.sdp.101.com/v1/actions/manage?page_size=30&page=1&f_subject=%E7%89%A9%E7%90%86%E6%88%96%E5%8E%86%E5%8F%B2%E5%9D%87%E5%8F%AF&s_subject=%E4%B8%8D%E6%8F%90%E5%86%8D%E9%80%89%E7%A7%91%E7%9B%AE%E8%A6%81%E6%B1%82

这个url是经过编码的,看起来很乱,但是你放到网址查询框里解析出中文之后你就明白是什么意思了。

page:页面大小
f_subject:首选科目
s_subject:再选科目


接下来,就是一个难点出现了:咱不知道它有多少页,咱也不想去看它有多少页。
但是就算是个空页面,也是可以被爬下来的,只不过爬到的是空数据。
在解析的时候就会卡住。

最后想了个土办法才解决掉,但是感觉不是很好。


但是,今天我又重新审视了一下,发现了网址中的另一个参数:page_size。

只要我给一个足够大的page_size,我管你几页到底啊?反正就都在一页给我到底。

开个玩笑啊,适当调节页面大小就好了,该判断还是判断一下,因为我爬完发现,这些不同的选项搭配,获取的数据量天差地别。


代码实现

# #coding:utf-8

import requests
from lxml import etree
import random

user_agent_list = [
    "Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15",
    ]



def get_html(url,times):
    '''
    这是一个用户获取网页源数据的函数
    :param url: 目标网址
    :param times: 递归执行次数
    :return: 如果有,就返回网页数据,如果没有,返回None
    '''
    try:
        res = requests.get(url = url,headers = {
   
            "User-Agent":random.choice(user_agent_list)
            })   #带上请求头,获取数据
        if res.status_code>=200 and res.status_code<=300:                     #两百打头的标识符标识网页可以被获取
            return res
        else:
            return None
    except Exception as e:
        print(e)        # 显示报错原因(可以考虑这里写入日志)
        if times>0:
            get_html(url,times-1)   # 递归执行


def get_data(html_data, Xpath_path):
    '''
    这是一个从网页源数据中抓取所需数据的函数
    :param html_data:网页源数据 (单条数据)
    :param Xpath_path: Xpath寻址方法
    :return: 存储结果的列表
    '''

    data = html_data.content
    data = data.decode().replace("<!--", "").replace("-->", "")  # 删除数据中的注释
    tree = etree.HTML(data)  # 创建element对象

    el_list = tree.xpath(Xpath_path)
    return el_list



import json

fsubject_name = ["物理或历史均可","仅物理","仅历史"]
ssubject_name = ['不提再选科目要求','地理必须选考方可报考','化学、地理均须选考方可报考','化学、地理选考其中一门即可报考','化学、生物均须选考方可报考','化学、生物选考其中一门即可报考','化学、思想政治选考其中一门即可报考','化学必须选考方可报考','生物、地理均须选考方可报考','生物、地理选考其中一门即可报考','生物、思想政治选考其中一门即可报考','生物必须选考方可报考','思想政治、地理均须选考方可报考','思想政治、地理选考其中一门即可报考','思想政治必须选考方可报考']

res = get_html('https://wjt-subject-tool-api.sdp.101.com/v1/actions/manage?page_size=30&page=' + str(1) + '&f_subject='+'物理或历史均可'+'&s_subject='+'化学、地理均须选考方可报考',2)

j_data = json.loads(res.content)

import openpyxl

wb = openpyxl.Workbook()
ws = wb.active

with open("新高考选科工具.txt",'w+') as w:
    for f in fsubject_name:
        for s in ssubject_name:
            cs = wb.create_sheet(f+'+'+s, 0)

            i = 1
            while (1):
                res = get_html('https://wjt-subject-tool-api.sdp.101.com/v1/actions/manage?page_size=30&page=' + str(i) + '&f_subject='+f+'&s_subject='+s,2)

                j_data = json.loads(res.content)

                if (j_data["items"] == []):
                    print("空界面,跳出")
                    break

                for data in j_data["items"]:
                    print([data['school_name'],data['subject_name'],data['fsubject'],data['ssubject']])
                    cs.append([data['school_name'],data['subject_name'],data['fsubject'],data['ssubject']])
                    #w.write(str([data['school_name'],data['subject_name'],data['fsubject'],data['ssubject']]))
                    # df = pd.DataFrame([data['school_name'],data['subject_name'],data['fsubject'],data['ssubject']])
                    # df.to_excel('新高考选科工具.xlsx',sheet_name=f+'+'+s)
                i += 1

wb.save('新高考选科工具.xlsx')
wb.close()


优化小思路

我准备将爬取和存储解耦合,放在不同的线程中执行,以提高效率。
这可以作为我《精写15篇,学会Python爬虫》的一个项目来做。


转载:https://blog.csdn.net/qq_43762191/article/details/115764651
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场