Streamlit+Selenium快速构建一个网络爬虫应用

项目需要从网上爬取数据,用了八爪鱼来进行测试,可以通过自定义任务,不需要编程即可实现对于数据的爬取,但是缺点是免费版本自定义任务有数量限制,另外在采集过程的控制上还不够便利,对于熟悉Python编程的人来说,可以选择用Selenium这个自动化测试的工具库来构建一个爬虫工具,然后通过Streamlit来快速搭建一个界面优美的Web应用。以下是如何用这两个工具构建自己的爬虫工具的介绍。

网页分析

首先要分析要爬取的网站的特点,因为我是要爬取各个省纪委网站发布的通报案例,因此需要对这些网站的页面进行分析。以山西省纪委的网站为例,http://www.sxdi.gov.cn/xxgk/jdpg/qb/wfzybxgdjswt/index.html,在页面中可以看到有列举每个案例的标题,发布时间。在页面底部有跳转不同页面的链接。点击某个案例的标题,就跳转到具体案例的内容页面。因此对于这个网站,首先我们要提取所有的案例的标题和发布时间,通过分析页面可知,页面的<ul class="yw-con">这个列表标签里面包含了很多的<li>列表项,每一项对应一个案例标题和时间,在<li>列表项里面的<a>标签是案例内容的链接。在页面底部的下一页的按钮,其对应的标签是<a class="layui-laypage-next">,分析了这些信息之后,我们就可以针对这些特征来提取相应的内容了。对于其他纪委网站的网页,其特征也是大同小异,都可以通过这些方法来进行分析提取特征。

下面我们可以定义一个Json格式的配置文件,把各个纪委网站要提取的内容的特征写到配置文件里面,如下是山西纪委和中纪委这两个网站的配置:

{
    "中纪委-违反中央八项规定精神的通报": {
        "start_page": "https://www.ccdi.gov.cn/jdjbnew/wfbxgd/index.html",
        "next_page_click_class": "a.next",
        "list_class": "ul.list_news_dl2",
        "list_element_tag": "li",
        "content_class": "div.content"
    },
    "山西纪委-违反中央八项规定精神的通报": {
        "start_page": "http://www.sxdi.gov.cn/xxgk/jdpg/qb/wfzybxgdjswt/index.html",
        "next_page_click_class": "a.layui-laypage-next",
        "last_page_class": "a.layui-laypage-next.layui-disabled",
        "list_class": "ul.yw-con",
        "list_element_tag": "li",
        "content_class": "div.nrs-con",
        "same_page": true
    }
}

解释一下这个配置文件,其中start_page是这个网站的首页地址,next_page_click_class是下一页这个按钮的css类,last_page_class这个是当点击到最后一页时,下一页这个按钮的css类。不同的网站设计不一样,例如中纪委的网站当点击到最后一页时,下一页这个按钮消失,但是对于山西纪委的网站,当点击到最后一页时,下一页这个按钮会应用不同的css类,变成灰色。list_class是标题列表项的标签css类,list_element_tag是每一个列表项的标签,content_class是每个案例页面里面显示案件内容这个信息所对应的css类,same_page为true表示网站点击下一页的网页url不变。

Selenium安装与使用

Selenium是一个自动化Web浏览的工具,通常用于编写自动化测试脚本或者网络爬虫。其主要的核心组件是WebDriver,通过对应的驱动程序将Selenium的命令转换为浏览器的操作。考虑到很多网站都有反爬虫机制,Chrome的driver在应对这方面比较好,所以我采用的是ChromeDriver,注意下载Chromedriver的版本要和本地环境的Chrome浏览器的版本相对应。对于Ubuntu系统,需要把下载的ChromeDriver拷贝到/usr/local/bin目录下。

下面编写一个Python脚本来通过Selenium来爬取数据,代码如下:

from selenium.webdriver import Chrome
from selenium.webdriver import ChromeOptions
from selenium.webdriver.common.by import By
from selenium.common.exceptions import TimeoutException, NoSuchElementException, StaleElementReferenceException
import time
import tqdm
import pandas as pd
import argparse
from datetime import datetime
import json

parser = argparse.ArgumentParser(description='Process arguments.')
parser.add_argument('output', default="crawler_case.xlsx", help='输出结果的文件名,xlsx格式')
parser.add_argument('website', default="中纪委-违反中央八项规定精神的通报", help='要爬取的网站名')
parser.add_argument('--print_progress', type=bool, default=False, help='是否需要打印进度')
parser.add_argument('--records', type=int, default=0, help='抓取多少条数据,0表示全部')
parser.add_argument('--from_date', type=str, help='发布时间的开始日期, 格式为YYYY-MM-DD')
parser.add_argument('--to_date', type=str, help='发布时间的结束日期, 格式为YYYY-MM-DD')

args = parser.parse_args()
if args.from_date is not None:
    fromdate = datetime.strptime(args.from_date, "%Y-%m-%d")
else:
    fromdate = None
if args.to_date is not None:
    todate = datetime.strptime(args.to_date, "%Y-%m-%d")
else:
    todate = None

options = ChromeOptions()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
options.add_argument("--disable-blink-features")
options.add_argument("--disable-blink-features=AutomationControlled")
driver = Chrome(options=options)
driver.set_page_load_timeout(600)
driver.implicitly_wait(10)
page_browser = Chrome(options=options)
page_browser.set_page_load_timeout(10)

with open('crawler.json', 'r') as f:
    all_config = json.load(f)

config = all_config[args.website]


count = 0
results = []
flag = True

driver.get(config['start_page'])
while flag:
    retryCount = 0
    sleepTime = 1
    while retryCount<5:
        list_elements = driver.find_element(By.CSS_SELECTOR, config['list_class'])
        time.sleep(sleepTime)
        try:
            if config['list_element_tag'] is not None:
                elements = list_elements.find_elements(By.TAG_NAME, config['list_element_tag'])
            else:
                elements = list_elements.find_elements(By.CSS_SELECTOR, config['list_element_class'])
            break
        except StaleElementReferenceException:
            retryCount += 1
            sleepTime *= 2

    for i in tqdm.trange(len(elements)):
        item = elements[i]
        split_strs = item.text.split('\n')
        if len(split_strs) < 2:
            continue
        try:
            title = split_strs[0]
            publish_time = split_strs[1]
            publish_date = datetime.strptime(publish_time, "%Y-%m-%d")
        except ValueError:
            title = split_strs[1]
            publish_time = split_strs[0]
            publish_date = datetime.strptime(publish_time, "%Y-%m-%d")
        count += 1
        if fromdate is not None:
            if publish_date < fromdate:
                flag = False
                break
        if todate is not None:
            if publish_date > todate:
                continue
        link = item.find_element(By.TAG_NAME, 'a').get_attribute("href")
        try:
            page_browser.get(link)
            article = page_browser.find_element(By.CSS_SELECTOR, config['content_class']).text
            results.append([title, publish_time, article])
            time.sleep(0.5)
        except TimeoutException:
            count -= 1
        except NoSuchElementException:
            count -= 1
        if args.records > 0 and count >= args.records:
            flag = False
            break
    if len(results) > 0:
        df = pd.DataFrame(results, columns=['标题', '时间', '正文'])
        df.to_excel(args.output, header=True, index=False)
        if args.print_progress:
            print("Dataframe saved: " + args.output)
    if not flag:
        break
    try:
        next_page = driver.find_element(By.CSS_SELECTOR, config['next_page_click_class'])
    except NoSuchElementException:
        next_page = None
    try:
        last_page = driver.find_element(By.CSS_SELECTOR, config['last_page_class'])
    except NoSuchElementException:
        last_page = None
    except KeyError:
        last_page = None
    if last_page:
        flag = False
    elif next_page is None:
        flag = False
    else:
        initial_url = driver.current_url
        next_page.click()
        time.sleep(1)
        new_url = driver.current_url
        if "same_page" not in config and initial_url == new_url:
            flag = False

if args.print_progress:
    print("Crawler finished.")

在这个脚本里,可以通过传入参数来控制抓取多少条记录,以及设定发布时间的范围来抓取记录。

Streamlit编写Web应用

Streamlit 是一个开源的 Python 库,用于快速创建和分享交互式的 Web 应用程序,特别是在数据科学和机器学习领域。它允许开发者使用简单的 Python 代码来构建应用,而无需具备复杂的前端开发技能。

以下代码构建一个Web应用

from io import BytesIO
import streamlit as st
import pandas as pd
import numpy as np
import subprocess
import re
import datetime
from datetime import date
import json

st.write('### 纪委通报案例采集与整理')

tab1 = st.tabs(["案例爬取"])

#读取爬虫网站的配置
with open('crawler.json', 'r') as f:
    config = json.load(f)


with tab1:
    options = list(config.keys())
    selected_option = st.selectbox(
        "**请选择一个网站**",  # 标签文本
        options,           # 选项列表
        index=0            # 默认选中项的索引
    )
    records_number = st.number_input("**请输入要抓取的数据条数,0表示全部**", min_value=0)
    today = date.today()
    prev_year = today.year - 20
    prev = datetime.date(prev_year, 1, 1)
    d = st.date_input(
        "**选择要提取的案例发布时间的范围**",
        (prev, today),
        prev,
        today,
        format="YYYY.MM.DD"
    )
    button1 = st.button('爬取通报案例')
    placeholder1 = st.empty()
    placeholder2 = st.empty()

    if button1:
        with subprocess.Popen(
            ['python', 'crawler.py', 'temp.xlsx', selected_option,
            '--print_progress', 'True', '--records', str(records_number),
            '--from_date', d[0].strftime("%Y-%m-%d"), '--to_date', d[1].strftime("%Y-%m-%d")], 
            stdout=subprocess.PIPE, text=True) as p:
            placeholder1.markdown('处理中... 请等待!')
            for line in p.stdout:
                if not line.startswith('INFO') and not line.startswith('WARN'):
                # 更新进度条的文本信息
                    if line.startswith('Dataframe saved: '):
                        df = pd.read_excel('temp.xlsx', header=0)
                        placeholder2.write(df)
                    if line.startswith('Crawler finished'):
                        placeholder1.markdown('处理完成!')
                        # 将DataFrame转换为Excel格式的字节流
                        output = BytesIO()
                        with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
                            df.to_excel(writer, index=False, sheet_name='Sheet1')
                        output.seek(0)
                        st.download_button(
                            label="下载数据",
                            data = output.getvalue(),
                            file_name = "download.xlsx",
                            mime="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
                        )   

在以上代码中,通过Subprocess来调用之前编写的爬虫程序,通过获取程序打印的信息来了解执行的进度,并且定期把爬取的记录显示在页面上。

运行效果演示

通过Streamlit+Selenium实现的一个网络爬虫应用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/949401.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

动漫推荐系统django+vue前台后台完整源码

完整源码项目包获取→点击文章末尾名片&#xff01;

Chapter 1 Understanding Large Language Models

文章目录 Understanding Large Language ModelsWhat is an LLM?Applications of LLMSStages of building and using LLMsUsing LLMS for different tasksA closer look at the GPT architectureBuilding a large language modelSummary Understanding Large Language Models …

什么是VLAN?

VLAN&#xff08;Virtual Local Area Network&#xff0c;虚拟局域网&#xff09;是一种将物理局域网划分成多个逻辑上独立的虚拟网络的技术。VLAN不依赖于设备的物理位置&#xff0c;而是通过逻辑划分&#xff0c;将局域网内的设备虚拟地组织到同一组。这种技术允许网络管理员…

【君正T31开发记录】12.编译工具相关总结及介绍

移植交叉工具包的时候&#xff0c;发现这是很多工具的集合包&#xff1b;以及写makefile的时候&#xff0c;也需要了解下这些工具的作用及用法&#xff0c;这里总结记录一下常见的工具及相关用法。 g C编译器&#xff0c;用于编译C源代码文件&#xff0c;这个很常见&#xff0…

Appium(一)--- 环境搭建

一、Android自动化环境搭建 1、JDK 必须1.8及以上(1) 安装&#xff1a;默认安装(2) 环境变量配置新建JAVA_HOME:安装路径新建CLASSPath%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar在path中增加&#xff1a;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin&#xff1b;(3) 验证…

猫的眼睛有几种颜色?

在猫咪神秘而迷人的世界里&#xff0c;它们的眼睛犹如璀璨星辰&#xff0c;闪烁着各异的光芒&#xff0c;颜色丰富多样&#xff0c;令人着迷。 猫眼睛的颜色&#xff0c;粗略一数&#xff0c;常见的便有黄色、蓝色、绿色、棕色&#xff0c;还有那神秘的异瞳。这些色彩并非无端生…

PHP框架+gatewayworker实现在线1对1聊天--接收消息(7)

文章目录 接收消息的原理接收消息JavaScript代码 接收消息的原理 接收消息&#xff0c;就是接受服务器转发的客户端消息。并不需要单独创建函数&#xff0c;因为 ws.onmessage会自动接收消息。我们需要在这个函数里进行处理。因为初始化的时候&#xff0c;已经处理的init类型的…

校园周边美食探索及分享平台的设计与实现(源码+数据库+文档)

亲测完美运行带论文&#xff1a;文末获取源码 文章目录 项目简介&#xff08;论文摘要&#xff09;运行视频包含的文件列表&#xff08;含论文&#xff09;前台运行截图后台运行截图 项目简介&#xff08;论文摘要&#xff09; &#xff1a; 美食一直是与人们日常生活息息相关…

基于深度学习的视觉检测小项目(七) 开始组态界面

开始设计和组态画面。 • 关于背景和配色 在组态画面之前&#xff0c;先要确定好画面的风格和色系。如果有前端经验和美术功底&#xff0c;可以建立自己的配色体系。像我这种工科男&#xff0c;就只能从网络上下载一些别人做好的优秀界面&#xff0c;然后在photo shop中抠取色…

wps版excel中如何快速生成倒序序号?

使用wps办公软件打开的excel文件&#xff1a; 效果如下&#xff1a; 方法&#xff1a; 如&#xff1a;想生成此列序号从101~13序号&#xff0c;倒序排列。 在第1个格子中输入开头的最小数字&#xff1a;13 点击一下【13】这个单元格&#xff0c;然后鼠标放在右下角&#xff…

jupyter出现“.ipynb appears to have died. It will restart automatically.”解决方法

原因 解决方法&#xff1a;更新jupyter的版本 1.打开anaconda prompt 2、更新jupyter版本 在anaconda prompt输入以下指令 conda update jupyter如图&#xff1a;

【Flink CDC】Flink CDC的Schema Evolution表结构演变的源码分析和流程图

Flink CDC版本&#xff1a;3.2.1 说明&#xff1a;本文从SchemaOperator接收到&#xff0c;表结构变更事件开始&#xff0c;表结构变更事件应由source端产生&#xff0c;本文不讨论。 可以先看流程图&#xff0c;研究源码。 参考文章&#xff1a; Flink cdc3.0动态变更表结构—…

【编译原理与技术(李文生第二版)】期末复习

第五章 语法制导定义第五章 设计翻译方案√第六章 语义分析-类型表达式&#xff08;仅记录&#xff0c;没说考&#xff09;第七章 参数传递 √第七章 运行栈、display表 √例题1&#xff1a;来源&#xff1a;课件例题2&#xff1a;来源&#xff1a;教材7.4例题3&#xff1a;来源…

SpringBoot环境和Maven配置

SpringBoot环境和Maven配置 1. 环境准备2. Maven2.1 什么是Maven2.2 为什么要学 Maven2.3 创建一个 Maven项目2.4 Maven核心功能2.4.1 项目构建2.4.2 依赖管理2.4.3 Maven Help插件 2.5 Maven 仓库2.5.1本地仓库2.5.2 中央仓库2.5.3 私有服务器, 也称为私服 2.6 Maven设置国内源…

五个不同类型的数据库安装

一、 官方首页下载 打开 MySQL 官方首页&#xff0c;链接为&#xff1a; MySQL 进去社区后选择合适的版本进行安装 安装细节 依图一路next 点击finish结束安装 二、 在线YUM仓库 将该安装包的下载链接在 Linux 操作系统中按照以下命令直接进行下载 三、 二进制本地 通过该链接…

决定系数(R²分数)——评估回归模型性能的一个指标

目录 1.定义 2.计算举例 3. 结果分析 1.定义 R&#xff08;R平方&#xff09;分数&#xff0c;也称为决定系数&#xff0c;是用来评估回归模型性能的一个指标。它表示自变量解释因变量变异性的比例。R分数的取值范围通常在0到1之间&#xff0c;其值越接近1&#xff0c;说明…

基于单片机的直流稳压电源的设计(论文+源码)

1.系统方案设计 在本次直流稳压电源的设计中&#xff0c;其关键指标如下&#xff1a; 系统输入电压220V交流系统输出直流0到12V可调&#xff0c;步进可以达到0.1V电流最大输出可以到2A具有短路保护功能可以通过液晶或者数码管等显示设备显示当前输出电压 2. 电路图

排序算法——堆排序

什么是堆 堆就是一种特殊的二叉树&#xff0c;他有以下特点&#xff1a; 堆中某个节点的值总是不大于或不小于其父节点的值&#xff1b; 堆总是一棵完全二叉树。 堆又可以分为大根堆和小根堆 大根堆&#xff1a;根节点最大&#xff0c;每个节点都小于或等于父节点 小跟堆&am…

数据挖掘——聚类

数据挖掘——聚类 聚类K-meansKNN VS K-meansK-Nearest Neighbors (KNN)K-means K中心算法PAM算法 K-modes算法——解决数据敏感的问题KMeans算法 ——解决初始点选择问题K-中心点层次方法AGNES算法——最小距离单链接全链接平均链接 聚类评估K均值和K中心点的优缺点层次化聚类…

在线机考|2024华为实习秋招春招编程题(最新)——第3题_个性化歌单推荐系统_300分(十一)

题目内容 假设你是音乐服务的开发者,为了提高用户体验需要解决推荐歌单的同质化问题,保证推荐给用户的所有歌单不包含相同歌曲的。给定一个包含N个歌单和M条歌单重复记录,每个歌单用一个从1到N的整数编号,歌单重复记录包含两个歌单的ID,表示两个歌单有相同的歌曲。 你的任…