Python爬虫系列-让爬虫自己写爬虫(半自动化,代替人工写爬虫)

news2024/11/17 22:42:10

        现在的PC、手机客户端等终端设备大量使用了网页前后端技术,另外主流的网站也会经常会更新,导致以前一个月更新一次爬虫代码,变成了天天需要更新代码,所以自动化爬虫技术在当前就显得特别重要,最近我也是在多次更新某个爬虫后,突然有了这样的需求,尝试搜索了下相关信息,发现是有人弄过这东西,我想哪些大厂肯定也有爬虫工程师开发过这东西,但是都没有开源,找不到啥资料,所以我想写一篇这方面的东西,感兴趣的朋友可以看下去。

        首先,我们先确定下基本思路,我经常使用Requests+BeautifulSoup写爬虫,所以基本代码的模板很好写,如下:

code_template = """
import requests
from bs4 import BeautifulSoup

def crawl(url):
    response = requests.get(url)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')
    
    results = []
    SELECTORS_PLACEHOLDER
    
    return results

if __name__ == "__main__":
    url = "URL_PLACEHOLDER"
    results = crawl(url)
    for result in results:
        print(result)
    """

其中SELECTORS_PLACEHOLDER就是我们需要用程序动态填写的内容,这是根据爬虫自我填写的代码,输入的代码如下所示:
 那么我们跟这个程序根据什么爬虫那,其实也很简单,我们使用上一篇文章的例子,链接如下为:
Python爬虫系列-爬取小说20240703更新(Request方法)icon-default.png?t=N7T8https://blog.csdn.net/donglxd/article/details/140145498

我们先试试爬取某个章节部分,随便打开一篇文章,如下图:

选取一行字,比如正文的第一句:"京海市第四高中,新生报到日。" 把这句作为一个参数代入到我的程序中,同时把这篇文章的网址也代入到我的程序中如下:

把运行后的自动写的代码如下:

复制后新建一个python文件,粘贴进去,保存并运行,就会得到如下结果:

 

有人要问了,我的自动生成爬虫,只能爬取文本吗?不能爬取属性值吗?比如属性里的链接?当然可以,请看下图:

可以看到第一章的链接是"41594870.html",这个不是绝对链接,而是相对链接,需要拼接处理,这个很简单,我想稍微学过5分钟python字符串语法的都会。我们把这个"41594870.html"属性代入我的程序读取看看,参数设置如下:

生成的爬虫如下:
新建一个python文档运行看看:

可以看到爬取成功了,我们可以尝试把两者结合起来,写一个手动爬虫,如下:

import requests
from bs4 import BeautifulSoup
import time# 导入time库加延迟用

# def crawl(url):
def getText(url):#把crawl函数建立一个新名称,方便调用,这个函数和下面的函数名不同,已区分开功能(读取每章内容)
    response = requests.get(url)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')

    # results = []
    results = ""#把数组改成字符串拼接用
    elements = soup.select('html body #main .bookinfo.m10.clearfix .chaptercontent #content p')
    for element in elements:
        # results.append(element.get_text(strip=True))
        results = results + element.get_text(strip=True) + "\n"
    results = results + "\n"#每章之间空一行
    return results

# def crawl(url):
def getUrl(url):#把crawl函数建立一个新名称,方便调用,这个函数和下面的函数名不同,已区分开功能(读取每章网址)
    response = requests.get(url)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')

    # results = []
    elements = soup.select('html body #main .chapterlist .clearfix li a')
    with open("20.AI编程爬虫\\1.txt","a+",encoding="utf-8") as f:# 创建一个新的txt文档,记录小说内容。
        for element in elements:
            # results.append(element.get('href', 'N/A'))
            results = getText(url + "/" + element.get('href', 'N/A'))# 把主链接和href的相对链接拼合
            f.write(results)#写入每章内容到txt文档
            print("链接内容:" + url + "/" + element.get('href', 'N/A') + "写入成功!")#输出写入的链接
            time.sleep(3)#为了爬取稳定加点延迟
    # return results

if __name__ == "__main__":
    url = "https://www.feibzw.com/Html/51366"
    # results = getUrl(url)
    getUrl(url)
    
    # for result in results:
    #     print(result)

可以看到上面的代码中,我注释的代码都是原来两个爬虫里的,新加的代码都有注释说明,一行行写下来不难,这部分其实也可以自动化,但是可能每个网站的链接地址都不同,拼接方法也不同,所以我写了这个模板给大家套用,按实际情况改就行了,这个模板可以应付大多数小说网站。我在这只是教大家方法,希望有抛砖引玉的作用,授人以渔。

最后放上我的自动生成程序,免费提供给大家:

import requests
from bs4 import BeautifulSoup

def find_elements_by_text_or_attribute(url, text):
    # 发送请求并获取网页内容
    response = requests.get(url)
    response.raise_for_status()  # 检查请求是否成功
    html_content = response.text

    # 解析网页内容
    soup = BeautifulSoup(html_content, 'html.parser')

    # 查找所有包含目标文本的标签
    target_tags = set()
    for tag in soup.find_all(string=True):
        if text in tag:
            parent = tag.parent
            target_tags.add(parent)

    # 查找所有包含目标属性值的标签
    for tag in soup.find_all(True):  # True表示查找所有标签
        for attr, value in tag.attrs.items():
            if isinstance(value, list):
                value = ' '.join(value)
            if text in value:
                target_tags.add(tag)
                break

    return target_tags

def get_unique_selectors(target_tags):
    unique_selectors = set()
    for tag in target_tags:
        selectors = []
        for parent in tag.parents:
            if parent.name == '[document]':
                break
            if parent.get('id'):
                selectors.append(f"#{parent.get('id')}")
            elif parent.get('class'):
                selectors.append(f".{'.'.join(parent.get('class'))}")
            else:
                selectors.append(parent.name)
        selectors.reverse()
        selectors.append(tag.name)
        unique_selector = ' '.join(selectors)
        unique_selectors.add(unique_selector)

    return unique_selectors

def generate_crawler_code(url, selectors, is_attribute, attribute=None):
    code_template = """
import requests
from bs4 import BeautifulSoup

def crawl(url):
    response = requests.get(url)
    response.raise_for_status()
    soup = BeautifulSoup(response.text, 'html.parser')
    
    results = []
    SELECTORS_PLACEHOLDER
    
    return results

if __name__ == "__main__":
    url = "URL_PLACEHOLDER"
    results = crawl(url)
    for result in results:
        print(result)
    """

    selectors_code = ""
    for selector in selectors:
        selectors_code += f"elements = soup.select('{selector}')\n"
        selectors_code += f"    for element in elements:\n"
        if is_attribute:
            selectors_code += f"        results.append(element.get('{attribute}', 'N/A'))\n"  # 这里的N/A表示如果属性不存在返回默认值
        else:
            selectors_code += f"        results.append(element.get_text(strip=True))\n"

    final_code = code_template.replace("URL_PLACEHOLDER", url).replace("SELECTORS_PLACEHOLDER", selectors_code)
    return final_code

def crawl_generator(url, text):
    target_tags = find_elements_by_text_or_attribute(url, text)
    if target_tags:
        unique_selectors = get_unique_selectors(target_tags)
        attribute = None
        is_attribute = False

        # 检查是文本内容还是属性值
        for tag in target_tags:
            for attr, value in tag.attrs.items():
                if isinstance(value, list):
                    value = ' '.join(value)
                if text in value:
                    is_attribute = True
                    attribute = attr
                    break
            if is_attribute:
                break

        crawler_code = generate_crawler_code(url, unique_selectors, is_attribute, attribute)
        return crawler_code
    else:
        return "未找到包含目标文本或属性的元素。"

if __name__ == "__main__":
    url = "https://www.feibzw.com/Html/51366"  # 替换为目标网址
    text = "41594870.html"  # 替换为目标文本
    # url = "https://www.feibzw.com/Html/51366/41594870.html"  # 替换为目标网址
    # text = '''京海市第四高中,新生报到日。'''  # 替换为目标文本

    crawler_code = crawl_generator(url, text)
    print(crawler_code)

谢谢大家观看,再见! 

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

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

相关文章

Linux高并发服务器开发(十一)UDP通信和本地socket通信

文章目录 1 TCP和UDP的区别2 UDPAPI流程服务端流程客户端流程 代码服务端客户端 3 本地socket通信服务端客户端客户端代码 1 TCP和UDP的区别 2 UDP API 流程 服务端流程 客户端流程 代码 服务端 #include<sys/socket.h> #include<stdio.h> #include<arpa/in…

R语言学习,入门

我是一名6年开发经验的程序员&#xff0c;后端&#xff0c;大数据&#xff0c;前端都会。 现在加入了医疗行业&#xff0c;要做数据分析&#xff0c;前同事的实验室生信专业的&#xff0c;用的是R语言&#xff0c;为了跑通他的程序。就来学一下吧&#xff0c;看了一下好像挺简…

【网络安全的神秘世界】SQL注入(下)

&#x1f31d;博客主页&#xff1a;泥菩萨 &#x1f496;专栏&#xff1a;Linux探索之旅 | 网络安全的神秘世界 | 专接本 | 每天学会一个渗透测试工具 3.7 二次注入 不好挖这个漏洞&#xff0c;需要搞懂业务逻辑关系 二次注入通常是指在存入数据库时做了过滤&#xff0c;但是取…

介绍东芝TB62262FTAG芯片:高性能两相双极步进电机驱动器

在当今快速发展的科技领域&#xff0c;高性能的电机驱动器对于许多工程项目来说至关重要。东芝的TB62262FTAG这款两相双极步进电机驱动器采用PWM斩波技术&#xff0c;集成了多个先进功能&#xff0c;适用于各种工业和消费类应用。本文将详细介绍TB62262FTAG的参数、性能、优势及…

JVM原理(十三):JVM虚拟机类类加载器与双亲委派模型

1. 类加载器 Java虛拟机设计团队有意把类加载阶段中的“通过一个类的全限定名来获取描述该类的二进制字节流"这个动作放到Java虚拟机外部去实现&#xff0c;以便让应用程序自己决定如何去获取所需的类。实现这个动作的代码被称为“类加载器”(Class Loader)。 对于任意一…

任天堂称未来第一方游戏不会使用生成式AI

虽然EA、育碧、暴雪、Embracer等西方游戏厂商都大力支持生成式AI技术&#xff0c;但日本老牌游戏公司任天堂并不会追随这一步伐。任天堂已经确认该公司未来的第一方游戏不会使用生成式AI技术。 在公司最近的投资人问答会上&#xff0c;任天堂描绘了公司未来游戏愿景。在谈到AI技…

00 如何根据规律在变化中求发展?

你好&#xff0c;我是周大壮。目前&#xff0c;我已在搜索推荐等算法技术领域从事研发近 10 年&#xff0c;做过诸多流量分发领域的算法技术工作。 如今任公司同城的算法架构师、技术委员会人工智能分会委员、公司本地服务事业群算法策略部负责人&#xff0c;我主要负责公司集…

从搜索框的提示词中再探防抖和节流

前言 最近逛掘金时&#xff0c;看到了一篇文章。发现是我之前写过的一篇文章主题是防抖和节流的&#xff0c;看防抖时没感觉哪里不一样&#xff0c;但是当我看到节流时发现他的节流怎么这么繁琐(・∀・(・∀・(・∀・*)&#xff1f; 抱着疑惑的想法&#xff0c;我仔细拜读了这…

C语言版,链表头插法与尾插法

最近又开始看数据结构与算法&#xff0c;看到这个头插法还真的是头插法&#xff0c;头都搞疼了&#xff0c;略微理解了一些。尾插法还好一些&#xff0c;比较好理解&#xff0c;但是如果深入理解还是可以理解。 头插法核心代码&#xff1a; head->next NULL; s->next h…

C++11新特性【下】{lambda表达式、可变模板参数、包装器}

一、lambda表达式 在C98中&#xff0c;如果想要对一个数据集合中的元素进行排序&#xff0c;可以使用std::sort方法。如果待排序元素为自定义类型&#xff0c;需要用户定义排序时的比较规则&#xff0c;随着C语法的发展&#xff0c;人们开始觉得上面的写法太复杂了&#xff0c…

Linux高并发服务器开发(十)反应堆模型和线程池模型

文章目录 1 epoll反应堆2 线程池流程代码 3 复杂版本线程池代码 1 epoll反应堆 文件描述符 监听事件 回调函数 进行封装 创建socket设置端口复用绑定监听创建epoll树将监听文件描述符lfd上epoll树&#xff0c;对应的事件节点包括&#xff1a;文件描述符&#xff0c;事件epoll…

ASP.NET Core Blazor 5:Blazor表单和数据

本章将描述 Blazor 为处理 HTML 表单提供的特性&#xff0c;包括对数据验证的支持。 1 准备工作 继续使用上一章项目。   创建 Blazor/Forms 文件夹并添加一个名为 EmptyLayout.razor 的 Razor 组件。本章使用这个组件作为主要的布局。 inherits LayoutComponentBase<div …

UnityUGUI之三 Text

富文本 常用语法&#xff1a; 1.加粗 <b> text </b> 2.斜体 <i> text </i> 3.尺寸 <size?> text </size> 4.颜色 <color#ff0000> text </color>

qt 滚动区域简单实验

1.概要 有些时候&#xff0c;想用一个有限的区域显示更多的内容&#xff0c;且内容不固定用滚动区域控件是一个不错的选择&#xff0c;我今天就用一个图片简单的实验一下。 2.代码&#xff08;关键代码&#xff09; #include "widget.h" #include "ui_widget…

antd+vue——实现table组件跨页多选,已选择数据禁止第二次重复选择

需求场景&#xff1a;点击【新增】按钮可以在分页弹窗中跨页多选选择数据后添加到页面中&#xff0c;再次点击【新增】&#xff0c;已经选择过的数据则置灰不让重复选择。 选择后&#xff0c;置灰 点击【确定】数据添加到页面中&#xff0c;可再次点击【新增】进行添加数据 …

JS基础与Chrome介绍

导言 在Web开发中后端负责程序架构和数据管理&#xff0c;前端负责页面展示和用户交互&#xff1b;在这种前后端分离的开发方式中&#xff0c;以接口为标准来进行联调整合&#xff0c;为了保证接口在调用时数据的安全性&#xff0c;也为了防止请求参数被篡改&#xff0c;大多数…

C语言常见概念

目录 1. C语言是什么&#xff1f; 2. C语言的历史 3 编译和链接 4. VS项目和源文件、头文件介绍​编辑 5.创建项目 6.main函数​编辑 7. printf和库函数 8. 关键字介绍 9. 字符和ASCII编码 10. 字符串和\0 1. C语言是什么&#xff1f; 人和计算机交流的语言工具&…

CVD-Risk-Prevent 个性化心血管健康推荐系统:基于医学指南的规则框架与 LLM 的结合

CVD-Risk-Prevent 个性化心血管健康推荐系统&#xff1a;基于医学指南的规则框架与 LLM 的结合 提出背景推荐算法的选择选择疑问健康指标管理心血管风险因素目标设定实现目标的计划推荐的多维性 算法关键点&#xff1a;如何将心血管健康指标转换为多维推荐&#xff1f;确定风险…

热备路由HSRP与VRRP

一、什么是HSRP HSRP&#xff08;Hot Standby Router Protocol&#xff09;是Cisco的专有协议&#xff0c;用于实现网络中路由器的冗余和故障转移。通过HSRP&#xff0c;可以将多台路由器组成一个“热备份组”&#xff0c;形成一个虚拟路由器。在这个组内&#xff0c;只有一个…

理解Netty的核心概念

一、理解Netty Netty是一个用于开发高性能网络应用的框架。为了更容易理解它&#xff0c;下面一些描述&#xff0c;不一定准确&#xff0c;但一定容易理解。 从Netty的Channel开始&#xff0c;把Netty所有的核心概念都串起来。 Channel 简单理解为一个连接。 有一个特殊的C…