百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

Python网络爬虫框架的总结(python爬虫常用框架)

ccwgpt 2024-11-07 09:47 37 浏览 0 评论

前言

虽然使用reqeuests和bs4可以处理网站数据获取但是当你要爬去大批量的网页时,单独的使用reqeuests就显得力不从心了。因为这是两个层面的事情,解决的问题是不一样的。

网络爬虫

网络爬虫是一种强大的技术,通过查找一个或多个域名的所有 URL 来从 Web 网站收集需要的数据。Python 有一些流行的网络爬虫库和框架。

介绍简单的例子,使用两个库在 Python 中从头开始构建一个简单的网络爬虫:RequestsBeautiful Soup。接着使用 Scrapy 构建一个示例爬虫,从 IMDb 收集电影元数据,并查看 Scrapy 如何扩展到拥有数百万页面的网站。

什么是网络爬虫?

网络爬虫和网络抓取是两个不同但相关的概念。网页爬虫是网页抓取的一个组成部分,爬虫逻辑查找要由抓取工具代码处理的 URL。

网络爬虫从要访问的 URL 列表开始,称为种子。对于每个 URL,爬网程序会在 HTML 中查找链接,根据某些条件过滤这些链接,并将新链接添加到队列中。所有 HTML 或某些特定信息都被提取出来,由不同的管道进行处理。

其实简单的殂就是我们打开淘宝首页,有很多个链接可以点击,打开每个链接又会进入不同的链接,这些子链接也有更多的链接。爬虫可以处理这个形成蜘蛛网一样的链接。

网络爬虫策略

网络爬虫只会访问一部分网页,具体取决于爬虫预算,该预算可以是每个域的最大网页数、深度或执行时间。

许多网站都提供了一个机器人.txt文件,以指示可以抓取网站的哪些路径,哪些是禁止的。还有sitemap.xml,它比robots.txt更明确一些,专门指示机器人应该抓取哪些路径,并为每个URL提供额外的元数据。

流行的网络爬虫用例包括:

  • 搜索引擎(例如 Googlebot、Bingbot、Yandex Bot 等)收集了 Web 重要部分的所有 HTML。此数据已编制索引,使其可搜索。
  • 除了收集 HTML 之外,SEO 分析工具还收集元数据,例如响应时间、检测损坏页面的响应状态以及收集反向链接的不同域之间的链接。
  • 价格监控工具抓取电子商务网站以查找产品页面并提取元数据,尤其是价格。然后定期重新访问产品页面。
  • Common Crawl 维护一个开放的 Web 爬虫数据存储库。例如,2022 年 5 月的档案包含 34.5 亿个网页。


从头开始在 Python 中构建一个简单的网络爬虫

要在 Python 中构建一个简单的网络爬虫,至少需要一个库来从 URL 下载 HTML,另一个库来提取链接。Python 提供了用于执行 HTTP 请求的标准库 urllib 和用于解析 HTML 的 html.parser。可以在 Github 上找到一个仅使用标准库构建的示例 Python 爬虫。

还有其他流行的库,例如 RequestsBeautiful Soup,它们可以在编写 HTTP 请求和处理 HTML 文档时提供改进的开发人员体验。如果您想了解更多信息,可以查看有关最佳 Python HTTP 客户端的指南。

本地安装这两个库。

pip install requests bs4


import logging
from urllib.parse import urljoin
import requests
from bs4 import BeautifulSoup

logging.basicConfig(
    format='%(asctime)s %(levelname)s:%(message)s',
    level=logging.INFO)

class Crawler:

    def __init__(self, urls=[]):
        self.visited_urls = []
        self.urls_to_visit = urls

    def download_url(self, url):
        return requests.get(url).text

    def get_linked_urls(self, url, html):
        soup = BeautifulSoup(html, 'html.parser')
        for link in soup.find_all('a'):
            path = link.get('href')
            if path and path.startswith('/'):
                path = urljoin(url, path)
            yield path

    def add_url_to_visit(self, url):
        if url not in self.visited_urls and url not in self.urls_to_visit:
            self.urls_to_visit.append(url)

    def crawl(self, url):
        html = self.download_url(url)
        for url in self.get_linked_urls(url, html):
            self.add_url_to_visit(url)

    def run(self):
        while self.urls_to_visit:
            url = self.urls_to_visit.pop(0)
            logging.info(f'Crawling: {url}')
            try:
                self.crawl(url)
            except Exception:
                logging.exception(f'Failed to crawl: {url}')
            finally:
                self.visited_urls.append(url)

if __name__ == '__main__':
    Crawler(urls=['https://www.imdb.com/']).run()

(使用 Requests 库、使用 Beautiful Soup 库和过滤 URL),然后继续使用我们的 IMDb 起始 URL 实例化该类并调用其方法。Crawlerdownload_urlget_linked_urlsadd_url_to_visitrun()

只要 中存在待处理的 URL,就会运行,会将每个 URL 传递给 ,提取任何链接,并将它们添加到 - 冲洗并重复。runurls_to_visitcrawl()urls_to_visit

要运行我们的爬虫,只需在命令行中输入此命令即可。

python crawler.py

爬网程序为每个访问过的 URL 记录一行。

INFO:Crawling: https://www.imdb.com/
INFO:Crawling: https://www.imdb.com/?ref_=nv_home
INFO:Crawling: https://www.imdb.com/calendar/?ref_=nv_mv_cal
INFO:Crawling: https://www.imdb.com/list/ls016522954/?ref_=nv_tvv_dvd
INFO:Crawling: https://www.imdb.com/chart/top/?ref_=nv_mv_250
INFO:Crawling: https://www.imdb.com/chart/moviemeter/?ref_=nv_mv_mpm
INFO:Crawling: https://www.imdb.com/feature/genre/?ref_=nv_ch_gr

代码非常简单,但在成功抓取完整网站之前,有许多性能和可用性问题需要解决。

  • 爬网程序速度较慢,不支持并行性。从时间戳可以看出,抓取每个 URL 大约需要一秒钟。每次爬网程序发出请求时,它都会等待响应,不会执行太多其他操作。
  • 下载 URL 逻辑没有重试机制,URL 队列不是真正的队列,并且对于大量 URL 效率不高。
  • 链接提取逻辑不支持通过删除 URL 查询字符串参数来标准化 URL,不处理相对锚点/片段 URL(即 ),也不支持按域过滤 URL 或过滤掉对静态文件的请求。href="#myanchor"
  • 抓取工具不会识别自己,并忽略漫游器 .txt 文件。


使用 Scrapy 进行网络爬虫

Scrapy 是最受欢迎的网络抓取和抓取 Python 框架,。

Scrapy 具有多组件架构。通常实现至少两个不同的类:Spider 和 Pipeline。Web 抓取可以被认为是一种 ETL,在其中从 Web 中提取数据并将其加载到存储中。蜘蛛提取数据,管道将其加载到存储中。转换可以发生在爬虫和管道中,

可以在组件之间添加爬虫和下载器中间件,如下图所示。



Scrapy 架构概述 [源代码]

from scrapy.spiders import Spider

class ImdbSpider(Spider):
    name = 'imdb'
    allowed_domains = ['www.imdb.com']
    start_urls = ['https://www.imdb.com/']

    def parse(self, response):
        pass

Scrapy 还提供了几个通用的爬虫类:CrawlSpider、XMLFeedSpider、CSVFeedSpider 和 SitemapSpider。CrawlSpider 类继承自 Spider 基类,并提供额外的 rules 属性来定义如何抓取网站。每个规则都使用 LinkExtractor 来指定从每个页面中提取哪些链接。接下来,我们将通过为 IMDb(互联网电影数据库)构建爬虫来了解如何使用它们中的每一个。

为 IMDb 构建一个示例 Scrapy 爬虫

在尝试抓取 IMDb 之前,检查了 IMDb 机器人 .txt 文件,看看允许哪些 URL 路径。robots 文件仅禁止所有用户代理的 26 个路径。Scrapy 会事先读取 robot.txt 文件,并在 ROBOTSTXT_OBEY 设置为 时遵守该文件。使用 Scrapy 命令生成的所有项目都是这种情况。truestartproject

scrapy startproject scrapy_crawler

此命令使用默认的 Scrapy 项目文件夹结构创建一个新项目。

scrapy_crawler/

├── scrapy.cfg
└── scrapy_crawler
    ├── __init__.py
    ├── items.py
    ├── middlewares.py
    ├── pipelines.py
    ├── settings.py
    └── spiders
        ├── __init__.py

然后可以使用规则创建一个蜘蛛来提取所有链接。scrapy_crawler/spiders/imdb.py

from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor

class ImdbCrawler(CrawlSpider):
    name = 'imdb'
    allowed_domains = ['www.imdb.com']
    start_urls = ['https://www.imdb.com/']
    rules = (Rule(LinkExtractor()),)

现在,只需使用命令启动爬虫scrapy

scrapy crawl imdb --logfile imdb.log

将获得大量日志,包括每个请求的一个日志。在浏览日志时,我注意到,即使我们设置为仅抓取 https://www.imdb.com 下的网页,也会有对外部域(例如 amazon.com)的请求。allowed_domains


[scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://www.amazon.com/b/?&node=5160028011&ref_=ft_iba> from <GET [https://www.imdb.com/whitelist-offsite?url=https%3A%2F%2Fwww.amazon.com%2Fb%2F%3F%26node%3D5160028011%26ref_%3Dft_iba&page-action=ft-iba&ref=ft_iba](https://www.imdb.com/whitelist-offsite?url=https%3A%2F%2Fwww.amazon.com%2Fb%2F%3F%26node%3D5160028011%26ref_%3Dft_iba&page-action=ft-iba&ref=ft_iba)>

IMDb 将外部域下的路径重定向到外部域。有一个开放的 Scrapy Github 问题,该问题显示外部 URL 在应用之前不会被过滤掉。为了解决这个问题,可以将链接提取器配置为跳过以两个正则表达式开头的 URL。/whitelist-offsite/whitelistOffsiteMiddlewareRedirectMiddleware

class ImdbCrawler(CrawlSpider):
    name = 'imdb'
    allowed_domains = ['www.imdb.com']
    start_urls = ['https://www.imdb.com/']
    rules = (
        Rule(LinkExtractor(
            deny=[
                re.escape('https://www.imdb.com/offsite'),
                re.escape('https://www.imdb.com/whitelist-offsite'),
            ],
        )),
    )

Rule类支持多个参数来过滤 URL。例如可以忽略特定的文件扩展名,并通过对查询字符串进行排序或折叠来减少重复 URL 的数量。LinkExtractor

如果找不到用例的特定参数,则可以使用 LinkExtractor 或 Rule 的参数。例如两次获得相同的页面,一次是纯 URL,另一次是附加查询字符串参数。process_valueprocess_links

  • https://www.imdb.com/name/nm1156914/
  • https://www.imdb.com/name/nm1156914/?mode=desktop&ref_=m_ft_dsk

为了限制抓取的 URL 的数量,可以使用 w3lib 库中的 url_query_cleaner 函数从 URL 中删除所有查询字符串,并在 .process_links

from w3lib.url import url_query_cleaner

def process_links(links):
    for link in links:
        link.url = url_query_cleaner(link.url)
        yield link

class ImdbCrawler(CrawlSpider):

    name = 'imdb'
    allowed_domains = ['www.imdb.com']
    start_urls = ['https://www.imdb.com/']
    rules = (
        Rule(LinkExtractor(
            deny=[
                re.escape('https://www.imdb.com/offsite'),
                re.escape('https://www.imdb.com/whitelist-offsite'),
            ],
        ), process_links=process_links),
    )

现在已经限制了要处理的请求数,可以添加一种方法来从每个页面中提取数据并将其传递到管道进行存储。例如可以在不同的管道中对其进行处理,也可以选择 HTML 元数据。parse_itemresponse.text

要在标头标签中选择 HTML 元数据,可以指定自己的 XPath 表达式,最好使用库 extract 从 HTML 页面中提取所有元数据。

可以使用 .pip install extruct

import re
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from w3lib.url import url_query_cleaner
import extruct

def process_links(links):
    for link in links:
        link.url = url_query_cleaner(link.url)
        yield link

class ImdbCrawler(CrawlSpider):
    name = 'imdb'
    allowed_domains = ['www.imdb.com']
    start_urls = ['https://www.imdb.com/']
    rules = (
        Rule(
            LinkExtractor(
                deny=[
                    re.escape('https://www.imdb.com/offsite'),
                    re.escape('https://www.imdb.com/whitelist-offsite'),
                ],
            ),
            process_links=process_links,
            callback='parse_item',
            follow=True
        ),
    )

    def parse_item(self, response):
        return {
            'url': response.url,
            'metadata': extruct.extract(
                response.text,
                response.url,
                syntaxes=['opengraph', 'json-ld']
            ),
        }

该属性设置为,以便 Scrapy 仍然遵循每个响应的所有链接,配置了 extruct 以仅提取 Open Graph 元数据和 JSON-LD,这是一种在 Web 中使用 JSON 对链接数据进行编码的流行方法,由 IMDb 使用。可以运行爬网程序并将项目以 JSON 行格式存储到文件中。followTrue

scrapy crawl imdb --logfile imdb.log -o imdb.jl -t jsonlines

输出文件包含每个已爬网项的一行。例如,对于从 HTML 中的标记中获取的电影,提取的 Open Graph 元数据如下所示。imdb.jl<meta>


{
    "url": "http://www.imdb.com/title/tt2442560/",
    "metadata": {"opengraph": [{
         "namespace": {"og": "http://ogp.me/ns#"},
         "properties": [
             ["og:url", "http://www.imdb.com/title/tt2442560/"],
             ["og:image", "https://m.media-amazon.com/images/M/MV5BMTkzNjEzMDEzMF5BMl5BanBnXkFtZTgwMDI0MjE4MjE@._V1_UY1200_CR90,0,630,1200_AL_.jpg"],
             ["og:type", "video.tv_show"],
             ["og:title", "Peaky Blinders (TV Series 2013\u2013 ) - IMDb"],
             ["og:site_name", "IMDb"],
             ["og:description", "Created by Steven Knight.  With Cillian Murphy, Paul Anderson, Helen McCrory, Sophie Rundle. A gangster family epic set in 1900s England, centering on a gang who sew razor blades in the peaks of their caps, and their fierce boss Tommy Shelby."]
        ]
   }]}
}

单个项目的 JSON-LD 太长,无法包含在文章中,以下是 Scrapy 从标签中提取的内容的示例。<script type="application/ld+json">

"json-ld": [
    {
        "@context": "http://schema.org",
        "@type": "TVSeries",
        "url": "/title/tt2442560/",
        "name": "Peaky Blinders",
        "image": "https://m.media-amazon.com/images/M/MV5BMTkzNjEzMDEzMF5BMl5BanBnXkFtZTgwMDI0MjE4MjE@._V1_.jpg",
        "genre": ["Crime","Drama"],
        "contentRating": "TV-MA",
        "actor": [
            {
                "@type": "Person",
                "url": "/name/nm0614165/",
                "name": "Cillian Murphy"
            },
            ...
        ]
        ...
    }
]

通过按顺序点击过滤器,爬虫会生成内容相同的网址,只是过滤器的应用顺序不同。

  • https://www.imdb.com/name/nm2900465/videogallery/ content_type-拖车/related_titles-TT0479468
  • https://www.imdb.com/name/nm2900465/videogallery/ related_titles-TT0479468/content_type-拖车

长过滤器和搜索 URL 是一个难题,可以通过使用 Scrapy 设置限制 URL 的长度来部分解决,URLLENGTH_LIMIT。

以 IMDb 为例来展示在 Python 中构建网络爬虫的基础知识。如果需要来自 IMDb 的特定数据,可以查看提供每日 IMDb 数据导出的 IMDb 数据集项目或 Cinemagoer,

大规模 Web 爬虫

如果尝试抓取像 IMDb 这样拥有超过 1.3 亿个页面的大型网站(至少根据 Google 的数据),请务必通过调整您的爬虫并相应地调整其设置来负责任地抓取。

  1. USER_AGENT - 允许您指定用户代理并提供可能的联系方式
  2. DOWNLOAD_DELAY - 指定爬网程序在请求之间应等待的秒数
  3. CONCURRENT_REQUESTS_PER_DOMAIN - 指示爬网程序应向一个站点发送的最大并发请求数
  4. AUTOTHROTTLE_ENABLED - 启用自动和动态请求限制

请注意,默认情况下,Scrapy 爬网针对单个域进行了优化。如果要对多个网域进行爬网,请检查这些设置以针对广泛爬网进行优化,包括将默认爬网顺序从深度优先更改为呼吸优先。要限制抓取预算,可以使用关闭爬虫扩展程序的CLOSESPIDER_PAGECOUNT设置来限制请求数。

使用默认设置,Scrapy 每分钟为 IMDb 等网站抓取约 600 个页面。以这种速度,用一个机器人抓取 1.3 亿个页面大约需要半年时间。如果您需要抓取多个网站,最好为每个大型网站或网站组启动单独的爬虫。如果您对分布式 Web 爬网感兴趣,可以阅读开发人员如何使用 20 个 Amazon EC2 机器实例在不到两天的时间内使用 Python 抓取 250M 个页面。

在某些情况下,可能会遇到需要您执行 JavaScript 代码来呈现所有 HTML 的网站。否则,可能无法收集网站上的所有链接。因为现在网站在浏览器中动态渲染内容非常普遍,所以我编写了一个 Scrapy 中间件,用于使用 ScrapingBee 的 API 渲染 JavaScript 页面。

这一点主要是解决这种使用JavaScript动态生成HTML页面的情况。

结论

  • HTML是传统爬虫的关键
  • 新的WEB开发技术使用JavaScript来生成页面,实际爬虫任务比这个复杂
  • requests bs4 是基础的库,
  • scrapy是一个爬虫框架。

相关推荐

用Deepseek扩写土木工程毕业论文实操指南

用Deepseek扩写毕业论文实操指南一、前期准备整理现有论文初稿/提纲列清楚论文核心框架(背景、现状、意义、方法、数据、结论等)梳理好关键文献,明确核心技术路线二、Deepseek扩写核心思路...

985学霸亲授,DeepSeek也能绘6大科研图表,5分钟就出图

在实验数据处理中,高效可视化是每个科研人的必修课。传统绘图软件操作复杂、耗时费力,而智能工具DeepSeek的出现彻底改变了这一现状。本文将详解如何用DeepSeek一键生成六大科研常用图表,从思维导...

AI写论文刷屏?大学生正在丢掉的思考力

一、宿舍深夜:当论文变成"Ctrl+C+V"凌晨两点的大学宿舍,小王对着电脑屏幕叹气。本该三天前开始写的近代史论文,此刻还一片空白。他熟练打开某AI写作网站,输入"论五四运动的...

Grok在辅助论文写作上能不能既“聪明”又“可怕”?!

AcademicIdeas-学境思源AI初稿写作随着人工智能技术的飞速发展,论文写作这一学术任务正迎来新的助力。2025年2月18日,美国xAI公司推出了备受瞩目的Grok3模型,其创始人埃隆·...

大四论文沟通场景!音频转文字难题听脑AI来化解

大四学生都知道,写论文时和导师沟通修改意见,简直是“过关斩将”。电话、语音沟通完,想把导师说的修改方向、重点要求记下来,麻烦事儿可不少。手写记不全,用普通录音转文字工具,转完还得自己慢慢找重点,稍不注...

论文写作 | 技术路线图怎么画?(提供经典优秀模板参考)

技术路线图是一种图表或文字说明,用于描述研究目标、方法和实施计划。它展示了研究的整体框架和步骤,有助于读者理解研究的逻辑和进展。在课题及论文中,技术路线图是常见的一部分,甚至是一个类似心脏一样的中枢器...

25年信息系统项目管理师考试第2批论文题目写作建议思路框架

25年信息系统项目管理师考试第2批论文题目写作建议思路框架--马军老师

微信购物应尽快纳入法律框架(微信购物管辖)

符向军近日,甘肃省工商行政管理局发布《2016年上半年信息分析报告》。报告显示,微信网购纠纷迅猛增长,网络购物投诉呈上升趋势。投诉的主要问题有出售的商品质量不过关、消费者通过微信付款后对方不发货、购买...

泛珠三角区域网络媒体与腾讯微信签署《战略合作框架协议》

新海南客户端、南海网7月14日消息(记者任桐)7月14日上午,参加第四届泛珠三角区域合作网络媒体论坛的区域网络媒体负责人及嘉宾一行到腾讯微信总部座谈交流,并签署《战略合作框架协议》(以下简称《框架协...

离线使用、植入微信-看乐心Mambo手环如何打破框架

从2014年开始智能手环就成功进入人们的生活,至今已经演变出数据监测、信息推送、心率监测等诸多五花八门的功能,人们选择智能手环并不指望其能够改变身体健康情况,更多的是通过数据来正视自身运动情况和身体健...

微信私域电商运营策略与框架(微信私域怎么做)

...

华专网络:如何零基础制作一个网站出来?

#如何零基础制作一个网站出来?#你是不是觉得网站建设很复杂,觉得自己是小白,需求不明确、流程搞不懂、怕被外包公司坑……这些问题我都懂!今天华专网络就用大白话给你捋清楚建站的全流程,让你轻松get网站制...

WAIC2024丨明日上午9点,不见不散!共同探讨智能社会与全球治理框架

大咖云集,硕果闪耀WAIC2024世界人工智能大会智能社会论坛将于7月5日9:00-12:00与你相约直播间WAIC2024上海杨浦同济大学哔哩哔哩多平台同步直播探讨智能社会与全球治理框架WAIC...

约基奇:森林狼换来戈贝尔时大家都在嘲笑 他们的阵容框架很不错

直播吧5月4日讯西部季后赛半决赛,掘金将迎战森林狼,约基奇赛前接受采访。约基奇说道:“当蒂姆-康纳利(森林狼总经理、前掘金总经理&曾选中约基奇)做了那笔交易(换来戈贝尔)时,每个人都在嘲笑他...

视频号带货为什么一个流量都没有?顶级分析框架送给你

视频号带货为什么一个流量都没有?遇到问题,一定是步步来分析内容,视频号带货一个流量都没有,用另外一个意思来讲,就可以说是零播放。为什么视频号带货一个流量都没有?跟你说再多,都不如来个分析框架。1、是否...

取消回复欢迎 发表评论: