• selenium 知网爬虫之根据【关键词】获取文献信息


    哈喽大家好,我是咸鱼

    之前咸鱼写过几篇关于知网爬虫的文章,后台反响都很不错。虽然但是,咸鱼还是忍不住想诉苦一下

    有些小伙伴文章甚至代码看都没看完,就问我 ”为什么只能爬这么多条文献信息?“(看过代码的会发现我代码里面定义了 papers_need 变量来设置爬取篇数),”为什么爬其他文献不行?我想爬 XXX 文献“(因为代码里面写的是通过【知网高级搜索中的文献来源】来搜索文章),或者是有些小伙伴直接把代码报错贴给我,问我咋回事

    我觉得在网上看到别人的代码,不要一昧地拿来主义,复制粘贴就行了,你要结合你自己的本地环境对代码做适当地修改。比如定位 Xpath 元素路径,不通电脑或者说不同浏览器同一元素的 Xpath 路径有可能不是一样的,这个路径在我本地运行没问题,到了你那里就报错

    当看别人的代码时,最好先搞清楚:

    1. 别人是怎么想的
    2. 别人为什么要这么写
    3. 这么写的逻辑是什么?

    以我这几篇知网爬虫文章举例:

    1. 为什么要用 selenium 来爬取?
    2. 如何分析网页?如何定位元素?(Xpath、CSS 选择器等等)
    3. 如何通过 selenium 来模拟人为操作浏览器(鼠标移动、点击、滑动窗口等等)

    言归正传,咸鱼昨天收到一位粉丝私信说能不能根据【关键词】来搜索文献
    image
    今天这篇文章着重讲如何分析网页结构然后使用 selenium 根据知网的关键词来搜索文献。至于对搜索到的文献的爬取,本文不过多介绍,因为以前的文章已经写过了

    需求分析

    我们先来看下如果要通过关键词搜索文献,该怎么操作?

    知网:中国知网 (cnki.net)

    首先我们登录网站,点击【高级搜索】(也可以直接点击搜索框中的【主题】下拉选择)
    image
    然后我们点击【主题】——>选择【关键词】
    image
    image
    输入要搜索的关键词(例如:数字普惠金融)然后点击【检索】
    image

    网页分析&元素定位

    结合前面的需求分析,我们就可以对网页进行分析并定位出对应的元素

    首先是【高级搜索】,高级搜索有一个链接:高级检索-中国知网 (cnki.net),这样就能省掉一个步骤了

    然后我们需要点击 【主题】,才会出现下拉框。在分析网页的时候我发现当出现下拉框时,标签

  • ...
  • is not clickable at point (189, 249)

    就会使得程序点击不了【关键词】
    image
    而且我还发现如果加载不完全的话,需要鼠标移动到下拉框那里,让下拉框完全加载。所以这里我使用了 selenium 中的 ActionChains 来模拟鼠标的操作

    用 selenium 做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击、双击、点击鼠标右键、拖拽等等

    selenium 给我们提供了一个类来处理这类事件——ActionChains

    还有一点需要注意的是:如果鼠标只是移到【关键词】,下拉框其实还是不能正确加载出来,最好是移动到下拉框的最底部或者关键词后面的元素,这里我移动到【通讯作者】

    # 【通讯作者】定位
    /html/body/div[2]/div/div[2]/div/div[2]/div[1]/div[1]/div[2]/ul/li[8]
    
    li[data-val="RP"]
    

    image

    下拉框加载完成之后,定位到【关键词】再点击

        # 鼠标移动到下拉框
        ActionChains(driver).move_to_element(driver.find_element(By.CSS_SELECTOR, 'li[data-val="RP"]')).perform()
    
        # 找到[关键词]选项并点击
        WebDriverWait(driver, 100).until(
            EC.visibility_of_element_located((By.CSS_SELECTOR, 'li[data-val="KY"]'))).click()
    

    定位出搜索框,传入我们要搜索的关键词

        # 传入关键字
        WebDriverWait(driver, 100).until(
            EC.presence_of_element_located((By.XPATH, '''//*[@id="gradetxt"]/dd[1]/div[2]/input'''))
        ).send_keys(keyword)
    
        # 点击搜索
        WebDriverWait(driver, 100).until(
            EC.presence_of_element_located((By.XPATH, "/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/input"))
        ).click()
    

    搜索结果出来之后定位【文献条数】,获取对应的条数(text 标签)

        # 获取总文献数和页数
        res_unm = WebDriverWait(driver, 100).until(EC.presence_of_element_located(
            (By.XPATH, "/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[1]/span[1]/em"))
        ).text
    

    完整代码如下:

    import time
    from selenium import webdriver
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
    from selenium.webdriver.common.action_chains import ActionChains
    
    
    def webserver():
        # get直接返回,不再等待界面加载完成
        desired_capabilities = DesiredCapabilities.EDGE
        desired_capabilities["pageLoadStrategy"] = "none"
    
        # 设置微软驱动器的环境
        options = webdriver.EdgeOptions()
        # 设置浏览器不加载图片,提高速度
        options.add_experimental_option("prefs", {"profile.managed_default_content_settings.images": 2})
    
        # 创建一个微软驱动器
        driver = webdriver.Edge(options=options)
    
        return driver
    
    
    def open_page(driver, keyword):
        # 打开页面,等待两秒
        driver.get("https://kns.cnki.net/kns8/AdvSearch")
        time.sleep(2)
    
        # 修改属性,使下拉框显示
        opt = driver.find_element(By.CSS_SELECTOR, 'div.sort-list')  # 定位元素
        driver.execute_script("arguments[0].setAttribute('style', 'display: block;')", opt)  # 执行 js 脚本进行属性的修改;arguments[0]代表第一个属性
    
        # 鼠标移动到下拉框中的[通讯作者]
        ActionChains(driver).move_to_element(driver.find_element(By.CSS_SELECTOR, 'li[data-val="RP"]')).perform()
    
        # 找到[关键词]选项并点击
        WebDriverWait(driver, 100).until(
            EC.visibility_of_element_located((By.CSS_SELECTOR, 'li[data-val="KY"]'))).click()
    
        # 传入关键字
        WebDriverWait(driver, 100).until(
            EC.presence_of_element_located((By.XPATH, '''//*[@id="gradetxt"]/dd[1]/div[2]/input'''))
        ).send_keys(keyword)
    
        # 点击搜索
        WebDriverWait(driver, 100).until(
            EC.presence_of_element_located((By.XPATH, "/html/body/div[2]/div/div[2]/div/div[1]/div[1]/div[2]/div[2]/input"))
        ).click()
    
        # 点击切换中文文献
        WebDriverWait(driver, 100).until(
            EC.presence_of_element_located((By.XPATH, "/html/body/div[3]/div[1]/div/div/div/a[1]"))
        ).click()
    
        # 获取总文献数和页数
        res_unm = WebDriverWait(driver, 100).until(EC.presence_of_element_located(
            (By.XPATH, "/html/body/div[3]/div[2]/div[2]/div[2]/form/div/div[1]/div[1]/span[1]/em"))
        ).text
    
        # 去除千分位里的逗号
        res_unm = int(res_unm.replace(",", ''))
        page_unm = int(res_unm / 20) + 1
        print(f"共找到 {res_unm} 条结果, {page_unm} 页。")
    
    
    if __name__ == '__main__':
        keyword = "数字普惠金融"
        driver = webserver()
        open_page(driver, keyword)
    

    结果如下:
    image

  • 相关阅读:
    用 Python实现Python解释器
    金融核心系统云原生转型的三个挑战、六个误区和四个步骤
    人工智能轨道交通行业周刊-第24期(2022.11.21-11.27)
    最新绿豆APP源码苹果CMS影视插件版本/原生JAVA源码+反编译开源+免授权
    Spring Cloud Alibaba微服务第11章之MyBatis-plus
    正则表达式 || 遇到字符串里面有() 就在括号后面换行
    DSP-数字滤波器的结构
    IOT云平台 simple(3)springboot netty
    只因简历上有“精通”Redis,阿里三面被面试官狂问 Redis,再也不敢乱写了
    瑞吉外卖学习笔记3
  • 原文地址:https://www.cnblogs.com/edisonfish/p/17793652.html