美文网首页
Python爬虫入门例题:抓取牛客网题目

Python爬虫入门例题:抓取牛客网题目

作者: BABYMISS | 来源:发表于2020-05-21 15:57 被阅读0次

    最近做题的时候要写一些题解,在把牛客网的题目复制下来的时候,数学公式的处理比较麻烦,所以我用Python的selenium、urllib.request和BeautifulSoup4库对题目信息进行了爬取,写题解的时候时间节约了很多。

    2. 前期准备

    安装selenium、urllib和BeautifulSoup库。

    pip3 install urllib

    pip3 install selenium

    pip3 install beautifulsoup4

    3. 获取网页内容

    以 牛客网 NC204552 咪咪游戏 为例。

    # 导入库

    import urllib.request

    import bs4

    import time

    from bs4 import BeautifulSoup

    from selenium import webdriver

    # 题目属性

    problemId = "204552"

    # 打开浏览器,模拟登陆

    # 此处用的是Chrome,如果没有安装可以替换为其他支持的浏览器

    driver = webdriver.Chrome()

    获取网页内容

    # 获取页面内容

    # 题目链接

    url = f"https://ac.nowcoder.com/acm/problem/{problemId}"

    # 打开网页

    driver.get(url)

    # 网页加载等待时间

    time.sleep(3)

    # 找到 输入 用户名 和密码框,并且设置内容

    username = driver.find_element_by_id('jsEmailIpt')

    # 输入账号名,xxx替换为自己的账户名

    username.send_keys('xxx')

    time.sleep(1)

    password = driver.find_element_by_id('jsPasswordIpt')

    #输入密码,xxx替换为自己的密码

    password.send_keys('xxx')

    time.sleep(1)

    # 分析网页,找到登录按钮

    login = driver.find_elements_by_css_selector('div[class=col-input-login] a')[0]

    # 点击按钮

    login.click()

    time.sleep(3)

    # 格式化源代码

    soup = BeautifulSoup(driver.page_source,'lxml')

    # 退出浏览器

    driver.quit()

    存储和预处理

    # 存储

    data_dict = {}

    # 找到主体内容

    mainContent = soup.find_all(name="div", attrs={"class" :"terminal-topic"})[0]

    # 去除公式的重复html元素

    for each in mainContent.find_all('mrow'):

        each.decompose()

    for each in mainContent.find_all(name="span", attrs={"class" :"katex-html"}):

        each.decompose()

    # 更换换行符

    for each in mainContent.find_all('br'):

        each.replace_with("\n\n")

    4. 内容处理

    4.1. Limit

    先从比较简单的信息入手,找到题目标题、时间、和内存限制。

    # Limit

    # 找到题目标题、时间、和内存限制

    div = mainContent.find_all(name="div", attrs={"class":"subject-item-wrap"})[0].find_all("span")

    # 放入字典中存储

    data_dict['Title'] = f"牛客网 NC{problemId} " + soup.title.contents[0]

    # Time Limit

    data_dict['Time Limit'] = div[0].contents[0].split(':')[1]

    # Memory Limit

    data_dict['Memory Limit'] = div[1].contents[0].split(':')[1]

    定义函数,处理主体内容中诡异的空格和公式的符号。

    def divTextProcess(div):

        """

        处理<div>标签中的文本内容

        """

    #    获取文本

        strBuffer = div.get_text()

    #    替换公式标记

        strBuffer = strBuffer.replace("{", " $").replace("}", "$ ")

    #    去除多个空格

        strBuffer = strBuffer.replace("  ", "")

    #    去除多个换行符

        strBuffer = strBuffer.replace("\n\n\n", "\n")

    #    去除内容中用\xa0表示的空格

        strBuffer = strBuffer.replace("\xa0", "")

    #    去除首位空格

        strBuffer = strBuffer.strip()

        # 返回结果

        return strBuffer

    4.2. Problem Description

    获取题目描述

    # 处理题目描述

    div = mainContent.find_all(name="div", attrs={"class": "subject-question"})[0]

    data_dict['Problem Description'] = divTextProcess(div)

    4.3. Input

    输入描述

    div = mainContent.find_all(name="pre")[0]

    data_dict['Input'] = divTextProcess(div)

    4.4. Output

    输出描述

    div = mainContent.find_all(name="pre")[1]

    data_dict['Output'] = divTextProcess(div)

    4.5. Sample Input & Onput

    输入样例,用代码框环境包围。

    # Input

    div = mainContent.find_all(name="div", attrs={"class":"question-oi-cont"})[0]

    data_dict['Sample Input'] = "```cpp" + div.get_text() + '```'

    # Onput

    div = mainContent.find_all(name="div", attrs={"class":"question-oi-cont"})[1]

    data_dict['Sample Onput'] = "```cpp" + div.get_text() + '```'

    4.6. Note

    备注

    # 若有备注

    if len(mainContent.find_all(name="pre")) >= 5:

        div = mainContent.find_all(name="pre")[-1]

        data_dict['Note'] = divTextProcess(div)

    4.7. Source

    题目链接

    data_dict['Source'] = '[' + data_dict['Title'] + ']' + '(' + url + ')'

    5. 输出

    for each in data_dict.keys():

        print('### ' + each + '\n')

        print(data_dict[each].replace("\n\n**", "**").replace("**\n\n", "**") + '\n')

    下面是最后的输出结果

    ### Title

    牛客网 NC204552 咪咪游戏

    ### Time Limit

    C/C++ 1秒,其他语言2秒

    ### Memory Limit

    C/C++ 524288K,其他语言1048576K

    ### Problem Description

    牛牛最近喜欢玩咪咪游戏,于是自己写了个程序编了个游戏让牛妹来玩。游戏是这样的:

    牛牛有一个长的字符串(只包26含个小写字母),他想让牛妹判断这个字符串是好的。

    定义一个串是好的:这个串是由连续的mq连接而成的。

    比如 $mqmq$ 说明这个串是好的, $mqmqm$ 或 $mqmqx$ 都是不好的。现在牛牛 想问牛妹这个串是否是好的,如果好的输出 $Yes$ ,否则输出 $No$

    ### Input

    第一行一个整数Q,表示询问次数

    就下来Q行,一个字符串$s

    ### Output

    Q行,每行输出 $Yes$ 或 $No$

    ### Sample Input

    // 这里会有```cpp代码环境,在这里为了展示方便去掉了

    4

    mqmq

    mqmqm

    mqakioi

    mqqmmq

    ### Sample Onput

    Yes

    No

    No

    No

    ### Note

    对于 $60\%$ 的数据满足: $|s|<=10,Q<=10$ 且保证只出现m,q两个字符

    对于 $100\%$ 的数据: $|s| <=10^5,Q<=10$

    对于所有数据保证只出现26个英文小写字母

    ### Source

    [牛客网 NC204552 咪咪游戏](https://ac.nowcoder.com/acm/problem/204552)

    相关文章

      网友评论

          本文标题:Python爬虫入门例题:抓取牛客网题目

          本文链接:https://www.haomeiwen.com/subject/mrxtahtx.html