使用 Scrapy 实现网页抓取
介绍
许多人认为,数据是新的石油,因为它是一种越来越有价值的资源。随着互联网使用的增长,不同网站上的数据量巨大。如果您想从网页获取数据,一种方法是使用 API 或实施网络抓取技术。网络抓取器和爬虫会读取网站的页面和信息,并分析网站的结构和标记语言以寻找提取数据的线索。有时,从抓取中收集的数据会被输入到其他程序中进行验证、清理和输入到数据存储中。它也可能被输入到其他流程中,例如自然语言处理 (NLP) 工具链或机器学习 (ML) 模型。
您可以使用一些 Python 包进行网页抓取,包括 Beautiful Soup 和 Scrapy,本指南将重点介绍 Scrapy。Scrapy 使我们可以轻松快速地制作网页抓取工具的原型并进行开发。
在本指南中,您将了解如何抓取 IMDB 网站并将其部分数据提取到 JSON 文件中。
什么是 Scrapy?
Scrapy是一个用 Python 编写的免费开源网络爬虫框架。它是一个快速的高级框架,用于爬取网站并从其页面中提取结构化数据。它可以用于从数据挖掘到监控和自动化测试等各种目的。Scrapy 使用蜘蛛来定义应如何从网站中抓取信息。它让我们确定我们希望蜘蛛如何抓取、我们想要提取哪些信息以及如何提取这些信息。
设置和安装
让我们讨论一下安装、创建蜘蛛,然后测试它。
步骤 1:创建虚拟环境
最好为 Scrapy 创建不同的虚拟环境,因为这样可以隔离程序并且不会影响机器中存在的任何其他程序。
首先,使用以下命令安装虚拟环境。
$ pip install virtualenv
现在用 Python 创建一个虚拟环境。
$ virtualenv scrapyvenv
对于 Linux/Mac,您可以提及 Python 版本。
$ virtualenv -p python3 scrapyvenv
您还可以提及想要创建虚拟环境的 Python 版本。
创建虚拟环境后,激活它。
对于 Windows:
$ cd scrapyvenv
$ .\Scripts\activate
对于Linux / Mac:
$ cd scrapyvenv
$ source bin/activate
第 2 步:安装 Scrapy
大多数依赖项将自动安装。它们适用于 Python 2.7+。
- pip install:要使用pip安装,请打开终端并运行以下命令:
$ pip install scrapy
- conda 安装:要使用conda安装,请打开终端并运行以下命令:
$ conda install -c anaconda scrapy
如果您在安装 twisted 库时遇到问题,您可以在此处下载,然后在本地安装。
步骤3:创建Scrapy项目
由于 Scrapy 是一个框架,我们需要遵循框架的一些标准。要在 scrapy 中创建新项目,请使用命令startproject。我将我的项目命名为webscrapy。
$ scrapy startproject webscrapy
此外,这将创建一个包含以下内容的 webscrapy 目录:
webscrapy
├── scrapy.cfg -- deploy configuration file of scrapy project
└── webscrapy -- your scrapy project module.
├── __init__.py -- module initializer(empty file)
├── items.py -- project item definition py file
├── middlewares.py -- project middleware py file
├── pipelines.py -- project pipeline py file
├── settings.py -- project settings py file
└── spiders -- directory where spiders are kept
├── __init__.py
使用 Scrapy 实现网页抓取
创建一个蜘蛛
现在,让我们创建第一个蜘蛛。使用命令genspider,它采用蜘蛛的名称和它将抓取的 URL:
$ cd webscrapy
$ scrapy genspider imdb www.imdb.com
运行该命令后,Scrapy会自动在spider文件夹中创建一个名为imdb的Python文件。
当你打开那个蜘蛛imdb.py Python 文件时,你会看到一个名为imdbSpider的类,它继承了scrapy.Spider类并包含一个名为parse 的方法,我们将在后面讨论。
import scrapy
class ImdbSpider(scrapy.Spider):
name = 'imdb'
allowed_domains = ['www.imdb.com']
start_urls = ['http://www.imdb.com/']
def parse(self, response):
pass
这里有几点需要注意:
name:蜘蛛的名称。在本例中为ImdbSpider。当您必须维护数百个蜘蛛时,正确命名蜘蛛会让您轻松很多。
allowed_domains:可选字符串列表,包含允许此蜘蛛抓取的域。不属于此列表中指定的域名的 URL 请求将不会被跟踪。
parse(self, response):每当爬虫成功爬取一个URL时,就会调用此函数。
要运行此蜘蛛,请使用以下命令。在运行此命令之前,请确保您位于正确的目录中。
$ scrapy crawl imdb
请注意,上述命令将蜘蛛的名称作为参数。
IMDB 上的抓取
现在让我们从 IMDB 前 250 部电影的表中获取所有表条目,例如标题、年份和评级。
创建之前已经创建的蜘蛛imdb.py。
# importing the scrapy
import scrapy
class ImdbSpider(scrapy.Spider):
name = "imdb"
allowed_domains = ["imdb.com"]
start_urls = ['http://www.imdb.com/chart/top',]
def parse(self, response):
# table coloums of all the movies
columns = response.css('table[data-caller-name="chart-top250movie"] tbody[class="lister-list"] tr')
for col in columns:
# Get the required text from element.
yield {
"title": col.css("td[class='titleColumn'] a::text").extract_first(),
"year": col.css("td[class='titleColumn'] span::text").extract_first().strip("() "),
"rating": col.css("td[class='ratingColumn imdbRating'] strong::text").extract_first(),
}
运行上述imdb蜘蛛:
$ scrapy crawl imdb
您将获得以下输出:
{'title': 'The Shawshank Redemption', 'year': '1994', 'rating': '9.2'}
{'title': 'The Godfather', 'year': '1972', 'rating': '9.1'}
...
{'title': 'Swades', 'year': '2004', 'rating': '8.0'}
{'title': 'Song of the Sea', 'year': '2014', 'rating': '8.0'}
创建更高级的抓取工具
让我们更进一步地抓取 IMDB。让我们打开所有 250 部电影列表中每部电影的详细页面,然后获取所有重要特征,例如导演姓名、类型、演员等。
在开始创建蜘蛛之前,我们必须在itmes.py中创建电影和演员项目。
欲了解更多详情,请阅读此处的项目文档。
import scrapy
class MovieItem(scrapy.Item):
title = scrapy.Field()
rating = scrapy.Field()
summary = scrapy.Field()
genre = scrapy.Field()
runtime = scrapy.Field()
directors = scrapy.Field()
writers = scrapy.Field()
cast = scrapy.Field()
class CastItem(scrapy.Item):
name = scrapy.Field()
character = scrapy.Field()
现在已经创建了项目,让我们扩展蜘蛛。
利用这个蜘蛛,我们获取每个电影项目的 URL,并通过调用parseDetailItem请求该 URL ,它会从电影详细信息页面收集所有电影数据。
# importing the scrapy
import scrapy
from webscrapy.items import MovieItem, CastItem
class ImdbSpider(scrapy.Spider):
name = "imdb"
allowed_domains = ["imdb.com"]
base_url = "https://imdb.com"
start_urls = ['https://www.imdb.com/chart/top',]
def parse(self, response):
# table coloums of all the movies
columns = response.css('table[data-caller-name="chart-top250movie"] tbody[class="lister-list"] tr')
for col in columns:
# rating of the movie i.e., position in the table
rating = col.css("td[class='titleColumn']::text").extract_first().strip()
# url of detail page of that movie.
rel_url = col.css("td[class='titleColumn'] a::attr('href')").extract_first().strip()
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~