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

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

off999 2024-09-21 20:52 36 浏览 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是一个爬虫框架。

相关推荐

hdd硬盘和ssd(ssd硬盘和hdd硬盘是什么意思)

HDD硬盘和SSD硬盘是两种不同类型的电脑存储设备,它们有着以下区别:1.工作原理:HDD硬盘使用机械旋转的磁盘和读写磁头来存储和读取数据,而SSD硬盘则使用闪存存储数据,类似于USB闪存盘。2....

电脑免费软件下载大全(电脑上免费的下载软件)

正常情况下,如果我们想要在自己的电脑上面下载一个不要钱的单机游戏,那么我们是可以直接在我们的软件管理中心进行一个下载的,这个时候我们只需要通过一个权限就能够正常的下载,当然我们也是可以在一些小游戏的软...

mpp文件转换excel(mpp转换成pdf)

要将Excel表格转换为MPP格式,您可以按照以下步骤操作:1.打开Excel表格并确保数据按照项目的不同阶段或任务进行组织。2.将Excel表格中的数据复制到一个新的MicrosoftProj...

win7旗舰版开机密码忘记按f2

方法如下:开始-控制面板-用户帐户;在打开的更改用户帐户界面点击要更改的帐户;然后点击帐户左面的更改密码按钮;在打开的页面上,输入一次当前使用的密码,输入2次要更改的新密码然后保存退出就可以了...

笔记本无音频输出设备(笔记本无音频输出设备)

1、没有声卡驱动,解决方法就是找到笔记本的官网,下载电脑声卡的驱动安装即可。2、没有外界的音频播放设备,解决方法就是买一个外界的音频播放设备插到电脑主机的音频接口上即可。笔记本电脑显示未安装任何音频输...

iso文件能用手机打开吗(iso文件能用手机打开吗安全吗)

一般的压缩软件就可以打开的,比如,好压软件,这个打开只是解压形式的,如果你说的是运行iso文件,这个没有,况且安卓系统也不支持iso运行ISO文件一般用于光盘镜像文件的存储,如果想要在手机上运行ISO...

win7系统卡顿怎么优化(win7很慢很卡怎么优化)

1、首先打开安全卫士,进入安全卫士首页,单击软件窗口右下角的“更多”图标,打开扩展应用程序。2、单击选择“我的工具”。3、在我的工具菜单里面找到“人工服务”单击打开人工服务。4、在人工服务对话框有很多...

如何查看c盘微信聊天记录(如何查看c盘微信聊天记录内存大小)

微信群中的消息只要没删除基本都能保存,想要找微信群中几个多月前的消息可以直接根据日期来查找聊天记录。操作如下:1、打开想要查找记录的微信群,点击右上角人形图标;2、点击查找聊天内容;3、选择按日...

office2016家庭版激活密钥(office家庭版激活码2019)

走淘宝吧,因为零售版的密钥只能用一次。大概几块钱就能激活2016。如果你不在乎钱的话可以向我一样,订阅一个office365.实在不行可以和几个人一起买一个家庭版的365.出现这个情况,找微软申诉是没...

移动硬盘驱动器下载安装(移动硬盘驱动器下载安装教程)

1、右键单击您的桌面,选择“新建文件夹”,并命名该文件夹(例如“usb驱动程序”);2、然后到本站下载驱动程序;3、将其解压缩至在您的桌面上刚刚创建的usb驱动程序文件夹;4、单击开始菜单,然后选择设...

电脑硬盘格式化工具(电脑 格式化硬盘)

硬盘格式化工具很多,PQMACGIG8.0(中文就叫硬盘分区魔法师)是比较好的一个,这个是在WINDOWS下比叫好用,(个人感觉)FDISK也是比较好的一个,这个一般用在DOS下分区格式化WIN...

photoshop是一款什么软件(ps指的是什么软件)

这个说法是错误的,ps软件“即:photoshop”是由美国著名的“adobe阿多比”公司出品的专业的图像处理软件,它不是由微软公司出品的软件。众所周知的是,微软公司以设计视窗操作系统名满全球,它出...

ipad越狱的好处与坏处(ipad越狱好不好)

  好处一:  1、重命名、重组应用程序  如果你看着Sparrow(iOS最优秀邮件客户端)这个名字不爽,越狱之后就可以改成“Email”,如果你觉得“豆瓣电台”这个名字不给力,那就改成“中央人民广...

win7光盘重装系统步骤图解(win7光盘如何重装系统)

1.确认您的电脑支持从光盘启动。如果支持,可以直接将Windows7安装光盘插入电脑的光驱中。 2.打开电脑,按下F2、F10、F12或Delete等键进入BIOS设置界面。 ...

电脑已联网却无法上网(电脑已经联网了但是不能上网)

电脑连上网后,仍可能存在无法上网的情况,这可能是由多种原因造成的。以下是一些可能的原因和解决方法:1.浏览器问题:有时候,浏览器可能会出现故障,导致无法正常访问网络。您可以尝试清除浏览器的缓存和co...

取消回复欢迎 发表评论: