掘金 人工智能 前天 08:53
用 Trae 和 PyQt5 爬虫智能体轻松爬取掘金,自动化采集技术文章和数据(精英版)
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本文介绍了如何利用Trae智能开发工具和PyQt5框架,构建一个智能爬虫系统,自动化爬取掘金上的技术文章和数据。Trae能够自动生成代码、优化结构,显著提升开发效率。PyQt5则用于构建用户友好的界面,实现爬虫任务的可视化和交互控制。文章详细阐述了如何确定爬取目标、设置爬虫智能体、利用Trae提升开发效率,以及如何将PyQt5界面与爬虫集成,并探讨了应对掘金反爬机制的策略,为开发者提供了一个高效爬取掘金数据的解决方案。

🎯 **明确爬取目标与需求**:在掘金网站上,我们需要关注热门技术文章、各类专栏的内容、技术话题的最新动态以及用户评论和点赞数等互动数据,并根据需求选择爬取不同类型的页面,如文章列表、文章详情页、评论区等。

💡 **Trae 提升开发效率**:Trae 能够帮助我们自动生成爬虫所需的代码结构,并给出合理的命名建议,减少命名冲突的可能。同时,Trae 还能分析我们的爬虫逻辑,帮助我们发现潜在的性能瓶颈和优化点。

🖥️ **PyQt5 界面与爬虫集成**:利用 PyQt5 构建简洁的用户界面,方便启动和管理爬虫任务,通过界面上的按钮、进度条、文本框等组件,显示当前爬虫任务的进度,提供动态的控制按钮,并显示爬取的数据统计信息。

🛡️ **应对掘金的反爬机制**:针对掘金可能使用的防爬虫技术(如验证码、IP 限制等),我们可以使用代理 IP 和随机请求头来规避反爬。针对动态加载数据,可以使用 Selenium 或 Playwright 等工具模拟浏览器行为来抓取动态内容。

我用Trae 做了一个有意思的Agent 「网络爬虫专家」。 点击 s.trae.com.cn/a/bcea87 立即复刻,一起来玩吧!

爬虫技术已经成为了获取互联网上信息的强大工具。从新闻、博客到社交平台的数据抓取,爬虫都能为我们提供大量的有用资源。而今天,我想和大家分享如何利用 Trae 智能开发工具以及 PyQt5 框架,通过一个智能爬虫系统,自动化地爬取 掘金juejin.cn/)上的技术文章和数据。

掘金是一个极受开发者欢迎的技术社区,涵盖了最新的技术动态、开发技巧和实战经验。无论你是想了解某个技术的最新文章,还是获取流行技术趋势的数据,掘金都提供了丰富的信息资源。那么,如何才能高效且智能地从掘金网站上提取出这些有价值的内容呢?这正是今天我们要探讨的主题。

为什么选择 Trae 和 PyQt5?

Trae 是一款可以提高开发效率的智能开发工具,它不仅可以自动生成代码,还能提供代码命名、结构优化等辅助功能。通过 Trae,我们能够将原本需要花费大量时间的开发工作量,缩短到几分钟以内,极大地提升编写爬虫代码的效率和准确性。尤其在复杂的爬虫项目中,Trae 能够实时分析爬虫的结构和逻辑,提供合适的建议,帮助我们避免重复劳动和潜在错误。

PyQt5 是 Python 中最流行的桌面应用开发框架之一,它支持丰富的 UI 组件,并能够轻松构建跨平台的桌面应用。对于爬虫项目而言,PyQt5 可以帮助我们设计出用户友好的界面,提供灵活的交互方式,从而让整个爬取过程变得更加可视化和直观。更重要的是,PyQt5 可以与爬虫代码进行紧密集成,实现爬虫任务的动态显示与控制。

如何构建基于 PyQt5 的智能爬虫?

首先,我们需要明确自己爬取的目标内容。在掘金网站上,我们通常会关注以下几个方面的数据:

我们可以根据需求,选择爬取不同类型的页面(如文章列表、文章详情页、评论区等)

网络爬虫专家智能体提示词

角色设定 你是一名世界顶尖的网络爬虫专家,精通各类网站数据抓取技术。你拥有10年以上爬虫开发经验,擅长处理反爬机制、动态内容加载、验证码破解等复杂场景。

能力范围

    分析网站结构并设计高效爬取策略

    处理JavaScript渲染的动态内容

    绕过常见反爬机制(频率限制、User-Agent检测等)

    设计分布式爬虫架构

    数据清洗与存储方案

    合法合规的爬取建议

交互准则

    首先询问用户想要爬取的目标网站及具体需求

    分析技术可行性并提供多种解决方案

    详细解释每种方案的技术细节和潜在挑战

    强调合法合规性,提醒用户遵守robots.txt和网站条款

    提供代码示例时注明语言和所需库

    对复杂任务建议分阶段实施

在开发爬虫时,Trae 的作用尤为重要。它能够帮助我们自动生成爬虫所需的代码结构,并给出合理的命名建议。例如,当我们定义一个爬虫函数时,Trae 可以基于函数的功能和上下文,自动生成函数名,减少命名冲突的可能。同时,Trae 还能分析我们的爬虫逻辑,帮助我们发现潜在的性能瓶颈和优化点。

PyQt5 界面与爬虫集成

在实现爬虫功能的同时,我们还可以利用 PyQt5 构建一个简洁的用户界面,方便我们启动和管理爬虫任务。通过界面上的按钮、进度条、文本框等组件,我们可以:

这种集成不仅使得爬虫变得更加人性化,还能实时反馈爬取的进度和结果,让我们对爬虫的执行情况一目了然。

爬取掘金的挑战与应对策略

虽然掘金网站内容丰富,但爬虫过程中仍然存在一些挑战:

指令合集

1. 初始化爬虫项目

指令:初始化一个新的爬虫项目,命名为 JuejinCrawler

2. 导入所需库

指令: 导入请求库、HTML解析库和 PyQt5 库。

3. 爬虫目标设定

指令:设置爬虫目标为掘金网站,爬取技术文章、专栏和评论数据。

# Scrapy settings for JuejinCrawler project## For simplicity, this file contains only settings considered important or# commonly used. You can find more settings consulting the documentation:##     https://docs.scrapy.org/en/latest/topics/settings.html#     https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#     https://docs.scrapy.org/en/latest/topics/spider-middleware.htmlBOT_NAME = "JuejinCrawler"SPIDER_MODULES = ["JuejinCrawler.spiders"]NEWSPIDER_MODULE = "JuejinCrawler.spiders"ADDONS = {}# 设置 User-Agent,模拟浏览器访问USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36'# 允许的域名ALLOWED_DOMAINS = ['juejin.cn']# 起始 URLSTART_URLS = ['https://juejin.cn/']# Obey robots.txt rulesROBOTSTXT_OBEY = True# Configure maximum concurrent requests performed by Scrapy (default: 16)#CONCURRENT_REQUESTS = 32# Configure a delay for requests for the same website (default: 0)# See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay# See also autothrottle settings and docs#DOWNLOAD_DELAY = 3# The download delay setting will honor only one of:#CONCURRENT_REQUESTS_PER_DOMAIN = 16#CONCURRENT_REQUESTS_PER_IP = 16# Disable cookies (enabled by default)#COOKIES_ENABLED = False# Disable Telnet Console (enabled by default)#TELNETCONSOLE_ENABLED = False# Override the default request headers:#DEFAULT_REQUEST_HEADERS = {#    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",#    "Accept-Language": "en",#}# Enable or disable spider middlewares# See https://docs.scrapy.org/en/latest/topics/spider-middleware.html#SPIDER_MIDDLEWARES = {#    "JuejinCrawler.middlewares.JuejincrawlerSpiderMiddleware": 543,#}# Enable or disable downloader middlewares# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#DOWNLOADER_MIDDLEWARES = {#    "JuejinCrawler.middlewares.JuejincrawlerDownloaderMiddleware": 543,#}# Enable or disable extensions# See https://docs.scrapy.org/en/latest/topics/extensions.html#EXTENSIONS = {#    "scrapy.extensions.telnet.TelnetConsole": None,#}# Configure item pipelines# See https://docs.scrapy.org/en/latest/topics/item-pipeline.html#ITEM_PIPELINES = {#    "JuejinCrawler.pipelines.JuejincrawlerPipeline": 300,#}# Enable and configure the AutoThrottle extension (disabled by default)# See https://docs.scrapy.org/en/latest/topics/autothrottle.html#AUTOTHROTTLE_ENABLED = True# The initial download delay#AUTOTHROTTLE_START_DELAY = 5# The maximum download delay to be set in case of high latencies#AUTOTHROTTLE_MAX_DELAY = 60# The average number of requests Scrapy should be sending in parallel to# each remote server#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0# Enable showing throttling stats for every response received:#AUTOTHROTTLE_DEBUG = False# Enable and configure HTTP caching (disabled by default)# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings#HTTPCACHE_ENABLED = True#HTTPCACHE_EXPIRATION_SECS = 0#HTTPCACHE_DIR = "httpcache"#HTTPCACHE_IGNORE_HTTP_CODES = []#HTTPCACHE_STORAGE = "scrapy.extensions.httpcache.FilesystemCacheStorage"# Set settings whose default value is deprecated to a future-proof valueFEED_EXPORT_ENCODING = "utf-8"

4. 定义数据请求模块

指令:创建一个数据请求模块,发送 GET 请求到掘金网站,并模拟浏览器的 User-Agent

import requestsimport randomfrom selenium import webdriverfrom selenium.webdriver.chrome.options import Optionsfrom selenium.webdriver.common.by import Byimport time# 用户代理池USER_AGENTS = [    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36',    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.1 Safari/605.1.15',    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',    'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0',    # 可继续添加更多 User-Agent]# 代理池(示例,需替换为真实可用代理)PROXIES = [    'http://127.0.0.1:7890',    # 'http://user:pass@proxyserver:port',    # 可继续添加更多代理]def get_juejin(url, params=None):    """    发送 GET 请求到掘金网站,随机使用 User-Agent 和代理。    :param url: 请求的完整 URL    :param params: 可选的查询参数字典    :return: 响应内容(text),如请求失败返回 None    """    headers = {        'User-Agent': random.choice(USER_AGENTS)    }    proxies = None    if PROXIES:        proxy = random.choice(PROXIES)        proxies = {            'http': proxy,            'https': proxy        }    try:        response = requests.get(url, headers=headers, params=params, proxies=proxies, timeout=10)        response.raise_for_status()        return response.text    except requests.RequestException as e:        print(f"请求失败: {e}")        return Nonedef get_juejin_dynamic(url, wait_time=3, headless=True):    """    使用 Selenium 加载掘金网站动态内容。    :param url: 目标 URL    :param wait_time: 页面加载等待时间(秒)    :param headless: 是否无头模式    :return: 完整渲染后的页面 HTML    """    chrome_options = Options()    if headless:        chrome_options.add_argument('--headless')    chrome_options.add_argument('--disable-gpu')    chrome_options.add_argument('--no-sandbox')    chrome_options.add_argument(f'user-agent={random.choice(USER_AGENTS)}')    chrome_options.add_argument('--ignore-certificate-errors')    chrome_options.add_argument('--ignore-ssl-errors')    # 如需代理,可添加如下参数:    # chrome_options.add_argument('--proxy-server=http://127.0.0.1:7890')    driver = webdriver.Chrome(options=chrome_options)    try:        driver.get(url)        time.sleep(wait_time)  # 等待页面动态内容加载        html = driver.page_source        return html    finally:        driver.quit() 

5. 定义页面解析模块

指令:创建页面解析模块,使用 BeautifulSoup 提取文章标题、作者和发布时间。

from bs4 import BeautifulSoupdef parse_article(html):    """    解析掘金文章页面,提取标题、作者和发布时间。    :param html: 文章页面的 HTML 内容    :return: 字典,包含 title、author、publish_time    """    soup = BeautifulSoup(html, 'lxml')    # 标题    title_tag = soup.find('h1')    title = title_tag.get_text(strip=True) if title_tag else None    # 作者    author_tag = soup.find('a', class_='username')    author = author_tag.get_text(strip=True) if author_tag else None    # 发布时间    time_tag = soup.find('time')    publish_time = time_tag.get_text(strip=True) if time_tag else None    return {        'title': title,        'author': author,        'publish_time': publish_time    } 

6. 存储模块

指令:创建一个存储模块,将爬取的文章数据保存到 CSV 文件中。

import csvimport osdef save_articles_to_csv(articles, filename='articles.csv'):    """    将文章数据保存到 CSV 文件。    :param articles: 文章数据列表,每个元素为字典,包含 title、author、publish_time    :param filename: 保存的文件名,默认为 articles.csv    """    if not articles:        print("没有可保存的数据。")        return    fieldnames = ['title', 'author', 'publish_time']    file_exists = os.path.isfile(filename)    with open(filename, 'a', newline='', encoding='utf-8') as csvfile:        writer = csv.DictWriter(csvfile, fieldnames=fieldnames)        if not file_exists:            writer.writeheader()        for article in articles:            writer.writerow(article)    print(f"已保存 {len(articles)} 条数据到 {filename}")def save_articles_to_txt(articles, filename='articles.txt'):    """    将文章数据保存到 TXT 文件,每条数据一行,字段用制表符分隔。    :param articles: 文章数据列表,每个元素为字典,包含 title、author、publish_time    :param filename: 保存的文件名,默认为 articles.txt    """    if not articles:        print("没有可保存的数据。")        return    fieldnames = ['title', 'author', 'publish_time']    with open(filename, 'a', encoding='utf-8') as txtfile:        for article in articles:            line = '\t'.join(str(article.get(field, '')) for field in fieldnames)            txtfile.write(line + '\n')    print(f"已保存 {len(articles)} 条数据到 {filename}") 

7. PyQt5 界面

指令:创建 PyQt5 界面,包含开始、暂停、停止按钮,进度条和日志输出框。

8. 任务调度模块

指令:创建任务调度模块,手动触发爬虫任务的启动与停止。

from PyQt5.QtWidgets import (QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QProgressBar, QTextEdit, QApplication, QLabel)from PyQt5.QtCore import pyqtSignalimport sysimport threadingimport timefrom requester import get_juejin_dynamicfrom article_parser import parse_articlefrom cleaner import clean_articlefrom storage import save_articles_to_txtclass MainWindow(QWidget):    log_signal = pyqtSignal(str)    progress_signal = pyqtSignal(int)    def __init__(self):        super().__init__()        self.init_ui()        self._running = False        self._thread = None        self.log_signal.connect(self.log)        self.progress_signal.connect(self.progress_bar.setValue)    def init_ui(self):        # 按钮        self.start_btn = QPushButton('开始')        self.pause_btn = QPushButton('暂停')        self.stop_btn = QPushButton('停止')        # 进度条        self.progress_bar = QProgressBar()        self.progress_bar.setValue(0)        # 日志输出框        self.log_output = QTextEdit()        self.log_output.setReadOnly(True)        # 布局        btn_layout = QHBoxLayout()        btn_layout.addWidget(self.start_btn)        btn_layout.addWidget(self.pause_btn)        btn_layout.addWidget(self.stop_btn)        main_layout = QVBoxLayout()        main_layout.addLayout(btn_layout)        main_layout.addWidget(QLabel('进度'))        main_layout.addWidget(self.progress_bar)        main_layout.addWidget(QLabel('日志输出'))        main_layout.addWidget(self.log_output)        self.setLayout(main_layout)        self.setWindowTitle('掘金爬虫工具')        self.resize(500, 400)        self.start_btn.clicked.connect(self.start_crawl)        self.stop_btn.clicked.connect(self.stop_crawl)        self.pause_btn.setEnabled(False)    def log(self, msg):        self.log_output.append(msg)        self.log_output.ensureCursorVisible()    def start_crawl(self):        if self._running:            self.log_signal.emit('爬虫正在运行中...')            return        self._running = True        self.progress_signal.emit(0)        self.log_signal.emit('开始爬取掘金首页第一篇文章...')        self._thread = threading.Thread(target=self.crawl_task)        self._thread.start()    def stop_crawl(self):        if not self._running:            self.log_signal.emit('爬虫未在运行。')            return        self._running = False        self.log_signal.emit('已请求停止爬虫任务。')    def crawl_task(self):        try:            url = 'https://juejin.cn/'            html = get_juejin_dynamic(url)            if not html:                self.log_signal.emit('页面加载失败。')                self._running = False                return            self.progress_signal.emit(20)            # 解析首页,找到第一篇文章链接            import lxml.html            doc = lxml.html.fromstring(html)            article_links = doc.xpath('//a[contains(@href, "/post/")]/@href')            if not article_links:                self.log_signal.emit('未找到文章链接。')                self._running = False                return            first_article_url = 'https://juejin.cn' + article_links[0]            self.log_signal.emit(f'获取到第一篇文章链接: {first_article_url}')            self.progress_signal.emit(40)            article_html = get_juejin_dynamic(first_article_url)            if not article_html:                self.log_signal.emit('文章页面加载失败。')                self._running = False                return            self.progress_signal.emit(60)            article_data = parse_article(article_html)            if not article_data.get('title'):                self.log_signal.emit('未能正确解析文章内容。')                self._running = False                return            self.log_signal.emit(f"原始数据: {article_data}")            cleaned = clean_article(article_data)            self.log_signal.emit(f"清洗后数据: {cleaned}")            save_articles_to_txt([cleaned])            self.progress_signal.emit(100)            self.log_signal.emit('数据已保存到 articles.txt')        except Exception as e:            self.log_signal.emit(f'发生异常: {e}')        finally:            self._running = Falseif __name__ == '__main__':    app = QApplication(sys.argv)    window = MainWindow()    window.show()    sys.exit(app.exec_()) 

9. 反爬策略处理

指令:设置代理 IP 和用户代理来避免反爬。

import threadingclass CrawlerScheduler:    def __init__(self, crawl_func):        """        :param crawl_func: 爬虫主函数,需为可调用对象        """        self.crawl_func = crawl_func        self._thread = None        self._running = False    def start(self, *args, **kwargs):        if self._running:            print("爬虫已在运行中。")            return        self._running = True        self._thread = threading.Thread(target=self._run, args=args, kwargs=kwargs)        self._thread.start()        print("爬虫任务已启动。")    def _run(self, *args, **kwargs):        try:            self.crawl_func(*args, **kwargs)        finally:            self._running = False            print("爬虫任务已结束。")    def stop(self):        if not self._running:            print("爬虫未在运行。")            return        # 这里只能通过设置标志位让爬虫任务自行检查并退出        self._running = False        print("已请求停止爬虫任务。请确保爬虫主函数支持中断。")    def is_running(self):        return self._running 

10. 动态内容加载处理

指令:使用 Selenium 模拟浏览器来加载掘金网站的动态内容。

11. 清洗与处理爬取数据

指令:创建数据清洗模块,执行去除空值、日期格式化和提取关键词等操作。

import refrom datetime import datetimefrom typing import List, Dictdef clean_article(article: Dict) -> Dict:    """    清洗单条文章数据:去除空值、日期格式化、提取关键词。    :param article: 包含 title、author、publish_time 等字段的字典    :return: 清洗后的字典    """    # 去除空值    cleaned = {k: (v.strip() if isinstance(v, str) else v) for k, v in article.items() if v and str(v).strip()}    # 日期格式化(假设原始格式为 '2024-05-01 12:34' 或 '2024/05/01' 等)    if 'publish_time' in cleaned:        cleaned['publish_time'] = format_date(cleaned['publish_time'])    # 提取关键词(以标题为例,简单分词,实际可用更强分词工具)    if 'title' in cleaned:        cleaned['keywords'] = extract_keywords(cleaned['title'])    return cleaneddef format_date(date_str: str) -> str:    """    尝试将日期字符串格式化为标准 YYYY-MM-DD 格式。    :param date_str: 原始日期字符串    :return: 格式化后的日期字符串    """    for fmt in ('%Y-%m-%d %H:%M', '%Y-%m-%d', '%Y/%m/%d', '%Y.%m.%d'):        try:            dt = datetime.strptime(date_str, fmt)            return dt.strftime('%Y-%m-%d')        except Exception:            continue    # 若无法识别,原样返回    return date_strdef extract_keywords(text: str) -> List[str]:    """    简单提取关键词(以中文、英文分词为例,实际可用 jieba 等分词库)。    :param text: 输入文本    :return: 关键词列表    """    # 仅保留中英文、数字    text = re.sub(r'[^\u4e00-\u9fa5a-zA-Z0-9 ]', ' ', text)    # 按空格和常见分隔符分词    words = re.split(r'[\s,,。.!?、]+', text)    # 去除过短的词    keywords = [w for w in words if len(w) > 1]    return keywords 

12. 运行爬虫任务

我们来看一下最终的效果吧

自动化爬取,让技术文章触手可得

通过利用 Trae 和 PyQt5 的结合,我们可以轻松地开发一个功能强大的爬虫系统,自动化地抓取掘金网站上的技术文章和相关数据。不仅如此,使用 Trae 能够让我们在开发过程中更加高效、精准,减少代码错误和不必要的重复劳动。最终,我们得到的不仅仅是一个爬虫,而是一个可以高效运营、具备可视化管理界面的智能化爬虫系统,完美符合现代开发者的需求。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Trae PyQt5 网络爬虫 掘金 智能开发
相关文章