使用一个python脚本抓取大量网站【1/3】

news2024/12/27 13:20:36

一、说明

        您是否曾经想过抓取网站,但又不想为像Octoparse这样的抓取工具付费?或者,也许您只需要从网站上抓取几页,并且不想经历设置抓取脚本的麻烦。在这篇博文中,我将向您展示我如何创建一个工具,该工具能够仅使用 python 和一些 docker 免费抓取 90% 的网站。

二、可以抓取的数据类型

        大多数抓取机器人都是为了抓取表格数据或列表而创建的。在标记方面,表和列表本质上是相同的。在容器中,它们保存带有填充值的单元格的行。因此,脚本的算法:

Flowchart of application

三、抓取网站的过程

为了扩展潜在的抓取目标列表,我决定使用python和Selenium的老式组合。虽然我确实喜欢使用 Scrapy 并且在创建自己的解析脚本时受到其可配置设计的高度影响,但它在解析具有分页的站点方面有一定的限制,所以我不得不选择已经提到的解决方案。

为了稳定起见,我还决定使用 dockerized 版本的 chromedriver。在本地Chrome更新期间,它为我节省了一些痛苦,并且始终在那里,为我准备好了,与您在操作系统上安装的版本不同,该版本可能会因系统更新或安装新软件而混乱。

假设您的机器上已经运行了 docker 服务,使用 chromedriver 启动一个新容器就像运行两个命令一样简单:

docker pull selenium/standalone-chrome$ docker run -d -p 4444:4444 -p 7900:7900 — shm-size=”2g” selenium/standalone-chrome
My python script for scraping websites 

这篇文章的核心——代码共享段落。首先,我将向您介绍帮助程序方法:

from selenium import webdriver
from selenium.webdriver import Chrome, ChromeOptions
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

def get_local_safe_setup():
    options = ChromeOptions() 
    options.add_argument("--disable-blink-features")
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_argument("--disable-infobars")
    options.add_argument("--disable-popup-blocking")
    options.add_argument("--disable-notifications")

    driver = Chrome(desired_capabilities = options.to_capabilities())

    return driver

def get_safe_setup():
    options = ChromeOptions() 
    options.add_argument("--disable-dev-shm-usage") 
    options.add_argument("--disable-blink-features")
    options.add_argument("--disable-blink-features=AutomationControlled")
    options.add_argument("--disable-infobars")
    options.add_argument("--disable-popup-blocking")
    options.add_argument("--disable-notifications")

    driver = webdriver.Remote("http://127.0.0.1:4444/wd/hub", desired_capabilities = options.to_capabilities())

    return driver

当我需要在开发过程中调试某些内容时,这两个允许我在 Selenium 的 dockerized 版本和本地版本之间切换。

def get_text_by_selector(container, selector):
    elem = container.find_elements_by_class_name(selector)

    if len(elem) > 0:
        return next(iter(elem)).text.replace('\n',' ').strip()
    else: 
        print(f'Missing value for selector {selector}')
        return ''

        还有一种简单的方法可以从我正在使用的HTML元素中提取文本。在不久的将来,我计划添加助手以自动提取链接和图像。如果对这个主题感兴趣,我可以分享脚本的更新版本。

        这种硒基蜘蛛的本质在下面的要点中。请通读评论,如果对它的工作原理有任何疑问 - 请在评论中告诉我。

import os
import time

from tqdm import tqdm

import pandas as pd
import argparse

from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

from tools.helpers import get_text_by_selector
from tools.setups import get_safe_setup
from tools.loaders import load_config

class Spider:
    def __init__(self, driver, config):
        self.__driver = driver
        self.__config = config
    
    def parse(self, url: str) -> pd.DataFrame:
        """
            Scrapes a website from url using predefined config, returns DataFrame
            parameters:
                url: string
            
            returns:
                pandas Dataframe
        """
        self.__driver.get(url)
  
        container_element = WebDriverWait(self.__driver, 5).until(
            EC.presence_of_element_located((By.CLASS_NAME, self.__config['container_class']))
        )
            
        items = self.__driver.find_elements_by_class_name(self.__config['items_class'])
        items_content = [
            [get_text_by_selector(div, selector) for selector in self.__config['data_selectors']]
            for div in items]
        return pd.DataFrame(items_content, columns = self.__config['data_column_titles']) 

    def parse_pages(self, url: str):
        """
            Scrapes a website with pagination from url using predefined config, yields list of pandas DataFrames
            parameters:
                url: string
        """
        pagination_config = self.__config['pagination']        
        
        for i in tqdm(range(1, pagination_config['crawl_pages'] + 1)):
            yield self.parse(url.replace("$p$", str(i)))

            time.sleep(int(pagination_config['delay']/1000))      

def scrape(args): 
    config = load_config(args.config)

    pagination_config = config['pagination']
    url = config['url']

    driver = get_safe_setup()

    spider = Spider(driver, config)

    os.makedirs(os.path.dirname(args.output), exist_ok = True)

    try:
        if pagination_config['crawl_pages'] > 0:
            data = spider.parse_pages(url)
            df = pd.concat(list(data), axis = 0)
        else:
            df = spider.parse(url)
        
        df.to_csv(args.output, index = False)
    except Exception as e:
        print(f'Parsing failed due to {str(e)}')
    finally:
        driver.quit()

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--config', help='Configuration of spider learning')
    parser.add_argument('-o', '--output', help='Output file path')
    args = parser.parse_args()

    scrape(args)

四、如何使用脚本抓取网站

        在这一部分中,我将演示如何使用此脚本。首先,您需要创建一个 YAML 配置文件,然后运行爬虫。例如,让我们刮擦旧的 quotes.toscrape.com。它的配置示例如下所示:

url: https://quotes.toscrape.com/page/$p$/
container_class: col-md-8
items_class: quote
data_selectors:
  - text
  - author
  - keywords
data_column_titles:
  - Text
  - Author
  - Keywords
pagination:
 crawl_pages: 5
 delay: 5000

        首先,请注意 $p$ 是未来页码的占位符。这是因为大多数网站提供的页面内容在 URL 中发生了明显变化。你的任务是确定它是如何从一个页面到另一个页面的变化,并用这个面具为你的蜘蛛配置它。

        请注意,在data_selectors和data_column_titles中,顺序很重要。例如,引号的文本将从选择器“.text”(duh)解析。

        准备好配置后,您可以使用以下命令执行它:

python -m spider -c “./configs/quotes.yaml” -o “./outputs/quotes/$(date +%Y-%m-%d).csv” 

        上面的 Bash 行从“./configs/quotes.yaml”文件中获取配置,并将 CSV 文件中的结果存储到 “./outputs/quotes/current_date.csv

五、关于如何改进刮削过程的提示

  • 使用代理

Selenium 允许您传递代理 IP 地址,就像向其构造函数添加参数一样简单。 在StackOverflow有一个完美的答案,所以我不会尝试发明轮子。

  • 对要解析的网站保持温和

        检查机器人.txt并遵守。使用特定超时运行请求以平滑负载。使用计划在晚上或您认为站点的传入流量较低时运行脚本。

六、结果

        敏捷抓取机器人最好的事情之一是,您不必为要解析的每个站点编写新的机器人。您只需要一个可以针对每个站点或域进行调整的好脚本。回想一下你今年到目前为止的所有抓取项目——你想让我在我的脚本中添加什么?

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2023爱分析·信创云市场厂商评估报告:中国电子云

01 研究范围定义 信创2.0时代开启,信创进程正在从局部到全面、从细分到所有领域延展。在这个过程中,传统的系统集成,也在逐步向信创化、数字化及智能化转变。随着信创产业的发展,企业需要更多的技术支持和服务,而传统的系统集成已…

Laravel 框架资源嵌套.浅嵌套.自定义表单伪造.CSRF 保护 ④

![请添加图片描述](https://img-blog.csdnimg.cn/154d035aa4db42df99f3b01fbf287e46.gif#pic_center)作者 : SYFStrive 博客首页 : HomePage 📜: THINK PHP 📌:个人社区(欢迎大佬们加入) 👉&a…

暗黑版GPT流窜暗网 降低犯罪门槛

随着AIGC应用的普及,不法分子利用AI技术犯罪的手段越来越高明,欺骗、敲诈、勒索也开始与人工智能沾边。 近期,专为网络犯罪设计的“暗黑版GPT”持续浮出水面,它们不仅没有任何道德界限,更没有使用门槛,没有…

【Linux命令行与Shell脚本编程】第十六章 Shell函数

Linux命令行与Shell脚本编程 第一章 文章目录 Linux命令行与Shell脚本编程六.函数6.1.脚本函数基础6.1.1.创建函数6.1.2.使用函数 6.2.函数返回值6.2.1.默认的退出状态码6.2.2.使用return命令6.2.3.使用函数输出 6.3.函数中使用变量6.3.1.向函数传递参数6.3.2.在函数中处理变量…

【jvm】jvm整体结构(hotspot)

目录 一、说明二、java代码的执行流程三、jvm的架构模型3.1 基于栈式架构的特点3.2 基于寄存器架构的特点 一、说明 1.hotspot vm是目前市场上高性能虚拟机的代表作之一 2.hotspot采用解释器与即时编译器并存的架构 3.java虚拟机是用来解释运行字节码文件的,入口是字…

微服务技术栈(1.0)

微服务技术栈 认识微服务 单体架构 单体架构:将业务的所有功能集中在一个项目中开发,打成一个包部署 优点: 架构简单部署成本低 缺点: 耦合度高 分布式架构 分布式架构:根据业务功能对系统进行拆分&#xff0c…

深度学习和OpenCV的对象检测(MobileNet SSD图像识别)

基于深度学习的对象检测时,我们主要分享以下三种主要的对象检测方法: Faster R-CNN(后期会来学习分享)你只看一次(YOLO,最新版本YOLO3,后期我们会分享)单发探测器(SSD,本节介绍,若你的电脑配置比较低,此方法比较适合R-CNN是使用深度学习进行物体检测的训练模型; 然而,…

新西兰跨境电商购物网站多语言翻译系统快速开发

搭建一个新西兰跨境电商购物网站的多语言翻译系统,可以按照以下步骤进行快速开发: 步骤1:确定需求和目标 首先,你需要明确你的网站需要支持哪些语言,并确定你想要实现的多语言翻译系统的具体功能和目标。 步骤2&…

unity如何手动更改脚本执行顺序

在Unity中,脚本的执行顺序是由脚本的执行顺序属性决定的。默认情况下,Unity根据脚本在项目中的加载顺序来确定它们的执行顺序。然而,你可以手动更改脚本的执行顺序,以下是一种方法: 在Unity编辑器中,选择你…

【云原生】kubectl命令的详解

目录 一、陈述式资源管理方式1.1基本查看命令查看版本信息查看资源对象简写查看集群信息配置kubectl自动补全node节点查看日志 1.3基本信息查看查看 master 节点状态查看命名空间查看default命名空间的所有资源创建命名空间app删除命名空间app在命名空间kube-public 创建副本控…

Unity背包系统与存档(附下载链接)

下载地址: https://download.csdn.net/download/qq_58804985/88184776 视频演示: 功能: 拖动物品在背包中自由移动,当物品拖动到其他物品上时,和其交换位置.基于EPPlus的背包数据与位置保存 原理: 给定一个道具池表格与一个背包表格 道具池表格负责存储所有道具的信息 背…

岩土工程监测仪器多通道振弦传感器信号转换器应用于铁路监测

岩土工程监测仪器多通道振弦传感器信号转换器应用于铁路监测 岩土工程监测是工程建设和运营过程中必不可少的环节,它主要是通过对地下水位、土体应力、变形、固结沉降等参数进行实时监测,以保证工程施工和运营的安全性和稳定性。而多通道振弦传感器信号…

JavaScript数据结构【进阶】

注:最后有面试挑战,看看自己掌握了吗 文章目录 使用 splice() 添加元素使用 slice() 复制数组元素使用展开运算符复制数组使用展开运算符合并数组使用 indexOf() 检查元素是否存在使用 for 循环遍历数组中的全部元素创建复杂的多维数组将键值对添加到对象…

阶段总结(linux基础)

目录 一、初始linux系统 二、基本操作命令 三、目录结构 四、文件及目录管理命令 查看文件内容 创建文件 五、用户与组管理 六、文件权限与压缩管理 七、磁盘管理 八、系统程序与进程管理 管理机制 文件系统损坏 grub引导故障 磁盘资源耗尽 程序与进程的区别 查…

Grafana V10 告警推送

最近项目建设完成,一个城域网项目,相关zabbix和grafana展示已经完,想了想,不想天天看平台去盯网络监控平台,索性对告警进行分类调整,增加告警的推送,和相关部门的提醒,其他部门看不懂…

绿盾用户使用看图软件每次都需要把图片解密之后才能打开查看,怎么才能不用这么麻烦打开就能看

环境: Win10专业版 绿盾控制台7.0 看图软件FastStone Image Viewer 问题描述: 绿盾用户使用看图软件FastStone Image Viewer每次都需要把图片解密之后才能打开查看,怎么才能不用这么麻烦打开就能看,用户说每次都需要把图片解密之后才能使用,实在是影响效率 解决方案…

4、长度最小的子数组

找到一个数组中,有多少个连续元素的和小于某个值,求出连续元素的长度的最小值。 滑动窗口法: 其本质也是快慢指针,一个指针指向窗口的起始位置,另一个指针指向窗口的终止位置。 1.定义快慢指针: 2.更新慢指…

css-3:什么是响应式设计?响应式的原理是什么?如何做?

1、响应式设计是什么? 响应式网站设计(Responsive WEB desgin)是一个网络页面设计布局,页面的设计与开发应当根据用户行为以及设备环境(系统平台、屏幕尺寸、屏幕定向等)进行相应的相应和调整。 描述响应式…

Unity 实现字幕打字效果

Text文本打字效果,TextMeshPro可以对应参考,差距不大,改改参数名就能用。改脚本原本被我集成到其他的程序集中,现在已经分离。 效果 实现功能 1.能够设置每行能够容纳的字数和允许的冗余 2.打字效果 3.每行打完上移 4.开头进入&…

项目实战 — 消息队列(5){统一硬盘操作}

前面已经使用数据库管理了交换机、绑定、队列,然后又使用了数据文件管理了消息。 那么,这里就创建一个类,讲之前的两个部分整合起来,对上层提供统一的一套接口,表示硬盘上存储的所有的类的信息。 /* * 用这个类来管理…