爬虫修炼手册,Python爬虫学习入门Scrapy
myzbx 2025-03-20 17:00 50 浏览
爬虫就如同江湖中的神秘侠客,应运而生,成为了我们获取数据的得力助手。爬虫,正式名称是网络爬虫(Web Crawler),也被叫做网页蜘蛛、网络机器人 ,它是一段神奇的计算机代码,能够自动在互联网的信息海洋中穿梭,抓取我们需要的数据。简单来说,爬虫就像是一个不知疲倦的信息采集员,按照我们设定的规则,自动访问网页,然后把网页中的文字、图片、链接等各种数据提取出来。
邂逅 Scrapy 大侠
在爬虫的江湖中,Scrapy 无疑是一位备受瞩目的大侠。它是用 Python 编写的一个快速、高层次的屏幕抓取和 Web 抓取框架,专为爬取网站数据、提取结构性数据而设计,在数据挖掘、监测和自动化测试等领域大显身手 。
Scrapy 之所以如此厉害,首先得益于它使用了 Twisted 异步网络框架。这就好比给爬虫装上了一双飞速奔跑的翅膀,能够异步处理多个请求,大大加快了下载速度,使得它在面对大量网页时,也能高效地完成数据抓取任务。举个例子,当我们需要从一个包含众多页面的电商网站上抓取商品信息时,Scrapy 可以同时向多个页面发送请求,而不需要像传统的同步方式那样,一个一个地等待请求完成,从而大大缩短了整个抓取过程的时间。
其次,Scrapy 内置了强大的 Selector(选择器),支持 XPath 和 CSS 选择器。这就如同给了我们一把精准的手术刀,能够在复杂的 HTML 和 XML 文档中,准确地定位和提取我们需要的数据。比如,我们想要提取网页中所有商品的名称和价格,使用 Scrapy 的 Selector,通过编写简单的 XPath 或 CSS 表达式,就能轻松地将这些数据从网页的代码中提取出来,而无需手动去逐行分析和筛选。
修炼第一步:项目结构
项目文件结构:
scrapy.cfg:这是项目的配置文件,主要用于部署项目到 Scrapy 服务器(如 Scrapyd)时的配置。虽然在日常开发中,我们可能不会频繁修改这个文件,但它对于项目的部署和管理是非常重要的。
项目同名文件夹(如 my_scrapy_project):这个文件夹是项目的核心代码所在,包含了多个重要的 Python 文件和一个spiders文件夹。它是整个项目的逻辑组织中心,所有与爬虫相关的代码、配置和数据处理逻辑都在这里定义和实现。
__init__.py:这是一个空文件,其作用是将所在的文件夹标记为一个 Python 包,这样 Python 解释器就可以识别并导入该文件夹中的模块。
items.py:在这个文件中,定义了爬虫要抓取的数据结构,也就是Item。Item类似于一个容器,用于存储从网页中提取的数据。比如我们要抓取电商网站上的商品信息,就可以在items.py中定义ProductItem,包含name(商品名称)、price(价格)、description(商品描述)等字段 。
middlewares.py:中间件文件,用于处理请求和响应的中间过程。我们可以在这里定义各种中间件,如用户代理中间件、代理 IP 中间件等。通过自定义用户代理中间件,可以在每个请求中随机更换用户代理,模拟不同的浏览器访问,从而提高爬虫的隐蔽性,降低被反爬虫机制检测到的风险。
pipelines.py:数据管道文件,主要用于处理爬虫提取到的数据。在这里可以进行数据清洗、存储到数据库、保存到文件等操作。比如,将爬取到的文章数据存储到 MySQL 数据库中,就可以在pipelines.py中编写相应的代码来实现数据的插入操作。
settings.py:项目的设置文件,包含了项目的各种配置参数,如爬虫的并发请求数、下载延迟、用户代理、启用的管道和中间件等。这些配置参数可以根据项目的需求进行调整,以优化爬虫的性能和行为。例如,通过设置DOWNLOAD_DELAY来控制下载页面的时间间隔,避免对目标网站造成过大的压力,从而防止被封禁 IP。
spiders文件夹:这个文件夹用于存放爬虫代码。每个爬虫都是一个 Python 类,继承自scrapy.Spider类,在这个文件夹中可以创建多个爬虫类,每个爬虫类负责从特定的网站或网页中抓取数据。例如,我们可以创建一个NewsSpider类来抓取新闻网站的文章,一个ImageSpider类来抓取图片网站的图片链接等。每个爬虫类都需要定义name(爬虫名称)、start_urls(起始 URL 列表)和parse方法(用于解析响应数据)等。
深入修炼:爬虫核心构建
(一)目标锁定:items.py
在 Scrapy 项目中,items.py文件就像是我们的寻宝地图,它定义了我们要从网页中抓取的数据结构,也就是Item。每个Item类都继承自scrapy.Item ,并定义了一系列的字段(Field),这些字段就是我们要抓取的数据项。
以爬取知乎用户信息为例,我们在items.py中定义如下:
import scrapy
class ZhihuUserItem(scrapy.Item):
# 用户ID
user_id = scrapy.Field()
# 用户名
username = scrapy.Field()
# 性别
gender = scrapy.Field()
# 关注数
following_count = scrapy.Field()
# 粉丝数
follower_count = scrapy.Field()在这个例子中,我们定义了一个ZhihuUserItem类,它包含了user_id、username、gender、following_count和follower_count等字段,这些字段就是我们想要从知乎用户页面中抓取的信息。通过这样的定义,我们就明确了爬虫的目标,后续在爬虫代码中,就可以按照这个结构来提取和存储数据。
(二)爬虫出鞘:spiders
spiders文件夹是存放爬虫代码的地方,每个爬虫都是一个 Python 类,继承自scrapy.Spider类。在这个类中,我们需要定义爬虫的名称、起始 URL 列表以及解析响应数据的方法。
以爬取知乎用户信息为例,我们创建一个ZhihuSpider类,代码如下:
import scrapy
class ZhihuSpider(scrapy.Spider):
name = 'zhihu'
allowed_domains = ['www.zhihu.com']
start_urls = ['https://www.zhihu.com/people/your_username']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, callback=self.parse)
def parse(self, response):
item = ZhihuUserItem()
item['user_id'] = response.css('meta[itemprop="identifier"]::attr(content)').get()
item['username'] = response.css('span.ProfileHeader-name::text').get()
gender = response.css('span.ProfileHeaderGender-icon::attr(class)').get()
item['gender'] = '男' if 'male' in gender else '女' if 'female' in gender else '未知'
item['following_count'] = response.css('a.Following-statusItem--following::text').get()
item['follower_count'] = response.css('a.Following-statusItem--followers::text').get()
yield item在这个爬虫类中:
name属性是爬虫的唯一标识,在运行爬虫时会用到,比如scrapy crawl zhihu ,这里的zhihu就是name的值。
allowed_domains指定了允许爬虫访问的域名,防止爬虫访问到其他不相关的网站,避免浪费资源和违反规定。
start_urls是爬虫的起始 URL 列表,爬虫会从这些 URL 开始发送请求。
start_requests方法生成初始的请求对象,它遍历start_urls列表,为每个 URL 生成一个scrapy.Request对象,并指定回调函数为parse方法。
parse方法是处理响应数据的核心方法,它接收下载器返回的响应对象response ,通过 CSS 选择器从响应的 HTML 中提取我们需要的数据,填充到ZhihuUserItem对象中,并使用yield返回该对象,这样数据就会被传递到后续的处理流程中。
(三)管道守护:pipelines.py
pipelines.py文件用于处理爬虫提取到的数据,它就像是一个数据加工厂,对爬取到的数据进行清洗、存储等操作。每个数据管道组件都是一个 Python 类,需要实现process_item方法,该方法接收一个Item对象和一个Spider对象作为参数,并返回一个Item对象或抛出DropItem异常。
以将爬取到的知乎用户信息存储到 MongoDB 为例,我们在pipelines.py中编写如下代码:
import pymongo
class MongoDBPipeline(object):
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DB')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def process_item(self, item, spider):
self.db['zhihu_users'].insert_one(dict(item))
return item
def close_spider(self, spider):
self.client.close()在这个管道类中:
__init__方法用于初始化管道,接收mongo_uri和mongo_db两个参数,分别表示 MongoDB 的连接地址和数据库名称。
from_crawler方法是一个类方法,用于从Crawler对象中获取设置信息,创建管道实例。
open_spider方法在爬虫启动时被调用,用于建立与 MongoDB 的连接。
process_item方法是核心处理方法,它将接收到的Item对象转换为字典,并插入到 MongoDB 的zhihu_users集合中,然后返回Item对象,以便后续的管道组件继续处理。
close_spider方法在爬虫关闭时被调用,用于关闭与 MongoDB 的连接。
同时,我们还需要在settings.py中配置启用这个管道,并设置相关的 MongoDB 连接信息:
ITEM_PIPELINES = {
'your_project_name.pipelines.MongoDBPipeline': 300,
}
MONGO_URI = 'mongodb://localhost:27017'
MONGO_DB = 'your_database_name'在上述配置中,ITEM_PIPELINES字典定义了启用的管道及其优先级,数值越小优先级越高。MONGO_URI和MONGO_DB分别设置了 MongoDB 的连接地址和数据库名称。通过这样的配置,爬虫在运行时,提取到的数据就会被传递到MongoDBPipeline中进行处理,最终存储到 MongoDB 数据库中。
(四)中间件助力:middlewares.py
中间件在 Scrapy 中起着重要的作用,它可以在请求和响应的处理过程中插入自定义的逻辑。Scrapy 的中间件主要分为下载中间件(Downloader Middleware)和爬虫中间件(Spider Middleware)。
下载中间件主要用于处理引擎发送到下载器的请求和从下载器返回到引擎的响应。它可以在请求发送前修改请求头、添加代理 IP、设置 Cookies 等,也可以在响应返回后对响应进行处理,如处理重定向、处理下载错误等。例如,我们可以使用下载中间件来随机更换 User - Agent,模拟不同的浏览器访问,从而提高爬虫的隐蔽性。
爬虫中间件则主要用于处理从引擎发送到爬虫的请求和从爬虫返回到引擎的响应。它可以在请求发送到爬虫之前对请求进行处理,如添加自定义的元数据;也可以在响应返回给引擎之前对响应进行处理,如对响应数据进行预处理、过滤等。
以自定义一个随机 User - Agent 中间件为例,我们在middlewares.py中编写如下代码:
from fake_useragent import UserAgent
from scrapy import signals
class RandomUserAgentMiddleware(object):
def __init__(self):
self.ua = UserAgent(use_cache_server=False)
def process_request(self, request, spider):
request.headers.setdefault('User-Agent', self.ua.random)在这个中间件类中:
__init__方法初始化UserAgent对象,use_cache_server=False表示不使用缓存服务器,直接从网络获取 User - Agent 列表。
process_request方法在每个请求发送前被调用,它从UserAgent对象中随机选择一个 User - Agent,并设置到请求头的User - Agent字段中,这样每个请求都会使用不同的 User - Agent,增加了爬虫的伪装性。
为了启用这个中间件,我们还需要在settings.py中进行配置:
DOWNLOADER_MIDDLEWARES = {
'your_project_name.middlewares.RandomUserAgentMiddleware': 400,
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware': None,
}在上述配置中,DOWNLOADER_MIDDLEWARES字典定义了下载中间件及其优先级。我们将自定义的RandomUserAgentMiddleware添加到中间件列表中,并设置其优先级为 400 。同时,将 Scrapy 默认的UserAgentMiddleware设置为None,表示禁用它,避免与我们自定义的中间件冲突。这样,在爬虫运行时,每个请求都会使用随机的 User - Agent,从而提高爬虫的稳定性和成功率。
实战演练:爬取知乎用户信息
(一)项目准备
在开始爬取知乎用户信息之前,我们需要进行一些准备工作。首先,确保我们已经创建了一个 Scrapy 项目,并在项目中定义了items.py、spiders、pipelines.py和middlewares.py等文件。
在settings.py文件中,我们需要进行一些配置,以确保爬虫能够正常运行。例如,设置请求头以模拟真实浏览器访问,避免被反爬虫机制检测到:
DEFAULT_REQUEST_HEADERS = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,\*/\*;q=0.8',
'Accept-Language': 'en',
}同时,为了避免对知乎服务器造成过大压力,我们还可以设置下载延迟,让爬虫在每次请求之间等待一段时间:
DOWNLOAD_DELAY = 1(二)代码实现
接下来,我们在spiders文件夹中创建一个爬虫类ZhihuSpider,用于爬取知乎用户信息。在这个爬虫类中,我们需要定义start_requests方法和parse方法。
start_requests方法用于生成初始的请求对象,我们从指定的知乎用户页面开始发送请求:
import scrapy
class ZhihuSpider(scrapy.Spider):
name = 'zhihu'
allowed_domains = ['www.zhihu.com']
start_urls = ['https://www.zhihu.com/people/your_username']
def start_requests(self):
for url in self.start_urls:
yield scrapy.Request(url, callback=self.parse)parse方法用于处理响应数据,从响应中提取我们需要的用户信息。这里以提取用户的基本信息(如用户名、关注数、粉丝数等)为例:
def parse(self, response):
item = {}
item['username'] = response.css('span.ProfileHeader-name::text').get()
item['following_count'] = response.css('a.Following-statusItem--following::text').get()
item['follower_count'] = response.css('a.Following-statusItem--followers::text').get()
yield item如果我们还需要爬取用户的关注列表,可以在parse方法中继续发送请求,获取关注列表的页面,并解析其中的用户信息。例如:
def parse(self, response):
item = {}
item['username'] = response.css('span.ProfileHeader-name::text').get()
item['following_count'] = response.css('a.Following-statusItem--following::text').get()
item['follower_count'] = response.css('a.Following-statusItem--followers::text').get()
yield item
# 爬取关注列表
following_url = response.css('a.Following-statusItem--following::attr(href)').get()
if following_url:
yield scrapy.Request(response.urljoin(following_url), callback=self.parse_following)
def parse_following(self, response):
for user in response.css('div.List-item'):
user_item = {}
user_item['username'] = user.css('a.UserLink-link::text').get()
user_item['user_url'] = user.css('a.UserLink-link::attr(href)').get()
yield user_item
# 处理分页
next_page = response.css('button.PaginationButton--next::attr(data-url)').get()
if next_page:
yield scrapy.Request(response.urljoin(next_page), callback=self.parse_following)(三)运行与结果
在完成代码编写后,我们可以使用以下命令运行爬虫:
scrapy crawl zhihu运行爬虫后,它会按照我们定义的规则开始爬取知乎用户信息。爬取到的数据会经过pipelines.py中定义的数据管道进行处理,例如存储到数据库中。如果我们在pipelines.py中定义了将数据存储为 JSON 格式的管道,爬取结果可能会类似如下:
[
{
"username": "张三",
"following_count": "100",
"follower_count": "500"
},
{
"username": "李四",
"following_count": "200",
"follower_count": "800"
}
]通过以上实战演练,我们可以看到如何使用 Scrapy 框架来爬取知乎用户信息,从项目准备、代码实现到最终运行获取结果,每个步骤都紧密相连,共同构成了一个完整的数据抓取过程。在实际应用中,我们还可以根据具体需求进一步优化爬虫,如增加代理 IP、处理验证码等,以提高爬虫的稳定性和成功率。
未来展望
在学习 Scrapy 爬虫的过程中,我就像是一个初入江湖的小侠客,从对爬虫一无所知,到逐渐掌握 Scrapy 的各项技能,能够独立完成一些简单的数据抓取任务,这个过程充满了挑战,但也收获满满。通过不断地实践和摸索,我不仅学会了如何使用 Scrapy 框架来编写高效的爬虫程序,还对网页的结构、HTTP 协议以及数据处理等方面有了更深入的理解。
对于想要学习 Scrapy 爬虫的朋友们,我建议大家在掌握了基本的语法和概念之后,一定要多进行实践。可以尝试从一些简单的网站开始爬取,逐渐积累经验,然后再挑战一些更复杂的网站。同时,不要害怕遇到问题,每一个问题都是我们成长的机会,通过解决问题,我们能够更好地理解和掌握 Scrapy 的原理和应用。
未来,随着互联网的不断发展,数据的价值也将越来越高。爬虫技术作为获取数据的重要手段,也将面临更多的挑战和机遇。一方面,网站的反爬虫机制会越来越强大,这就要求我们不断地学习和探索新的反反爬虫技术,提高爬虫的稳定性和成功率;另一方面,随着大数据、人工智能等技术的发展,对数据的质量和规模也提出了更高的要求,我们需要进一步优化爬虫的性能,提高数据抓取的效率和准确性。
同时,我们也要始终牢记,在使用爬虫技术时,一定要遵守法律法规和道德规范,不要进行恶意爬取,以免给他人和社会带来不良影响。希望大家都能在 Scrapy 爬虫的学习和实践中,收获自己的宝藏秘籍,成为数据江湖中的大侠!
相关推荐
- 如何设计一个优秀的电子商务产品详情页
-
加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...
- 怎么在JS中使用Ajax进行异步请求?
-
大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...
- 中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革
-
前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...
- 前端监控 SDK 开发分享_前端监控系统 开源
-
一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...
- Ajax 会被 fetch 取代吗?Axios 怎么办?
-
大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...
- 前端面试题《AJAX》_前端面试ajax考点汇总
-
1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...
- Ajax 详细介绍_ajax
-
1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...
- 6款可替代dreamweaver的工具_替代powerdesigner的工具
-
dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...
- 我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊
-
接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...
- 福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光
-
时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...
- 2021年超详细的java学习路线总结—纯干货分享
-
本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...
- 不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!
-
Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...
- 2025 年 Python 爬虫四大前沿技术:从异步到 AI
-
作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...
- 最贱超级英雄《死侍》来了!_死侍超燃
-
死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...
- 停止javascript的ajax请求,取消axios请求,取消reactfetch请求
-
一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...
- 一周热门
- 最近发表
- 标签列表
-
- HTML 简介 (30)
- HTML 响应式设计 (31)
- HTML URL 编码 (32)
- HTML Web 服务器 (31)
- HTML 表单属性 (32)
- HTML 音频 (31)
- HTML5 支持 (33)
- HTML API (36)
- HTML 总结 (32)
- HTML 全局属性 (32)
- HTML 事件 (31)
- HTML 画布 (32)
- HTTP 方法 (30)
- 键盘快捷键 (30)
- CSS 语法 (35)
- CSS 轮廓宽度 (31)
- CSS 谷歌字体 (33)
- CSS 链接 (31)
- CSS 定位 (31)
- CSS 图片库 (32)
- CSS 图像精灵 (31)
- SVG 文本 (32)
- 时钟启动 (33)
- HTML 游戏 (34)
- JS Loop For (32)
