使用python和scrapy制作网络爬虫的核心流程包括:安装scrapy、创建项目、定义spider、编写解析逻辑并利用选择器提取数据;2. scrapy通过设置user-agent、使用代理ip池、配置下载延迟和autothrottle、集成selenium或scrapy-splash等方式应对反爬机制;3. 数据存储与导出方式包括直接输出为json、csv、xml文件,或通过item pipelines将数据存入mysql、postgresql、sqlite、mongodb等数据库,也可推送至消息队列或云存储;4. 常见陷阱有选择器错误、allowed_domains限制、忽略robots.txt、异步逻辑误解和编码问题,调试技巧包括使用scrapy shell测试选择器、查看日志、保存响应内容、使用pdb断点调试以及设置dont_filter=true进行请求重试,最终通过持续测试与优化实现稳定抓取。

用Python制作网络爬虫,特别是借助Scrapy框架,这绝对是条高效且令人着迷的路径。Scrapy不只是一个库,它是一整套成熟的爬虫框架,帮你把数据抓取、处理、存储的很多繁琐工作都自动化了,让你能更专注于如何从页面上提取你真正想要的信息。
要用Python和Scrapy制作网络爬虫,核心流程其实挺清晰的,虽然初次接触可能会觉得概念有点多,但一旦上手,你会发现它真的能把效率拉满。
首先,你需要安装Scrapy。这很简单,打开你的终端或命令行,敲入:
pip install scrapy
安装完成后,我们通常会从创建一个Scrapy项目开始。这就像为你的爬虫任务搭一个脚手架:
scrapy startproject my_crawler_project
进入这个新创建的项目目录后,你就可以开始定义你的爬虫(Spider)了。Spider是Scrapy里最核心的部分,它定义了如何爬取一个网站以及如何从爬取到的页面中提取数据。你可以用命令生成一个基本的Spider:
cd my_crawler_project
scrapy genspider example_spider example.com
这会为你生成一个名为
example_spider.py
name
start_urls
parse
parse
立即学习“Python免费学习笔记(深入)”;
# my_crawler_project/my_crawler_project/spiders/example_spider.py
import scrapy
class ExampleSpider(scrapy.Spider):
name = "example_spider"
allowed_domains = ["example.com"] # 限制爬取范围,防止爬出界
start_urls = ["http://www.example.com/page1", "http://www.example.com/page2"]
def parse(self, response):
# 这是一个示例,假设我们要提取页面标题和链接
title = response.css('h1::text').get()
links = response.css('a::attr(href)').getall()
# 使用yield返回数据或新的请求
yield {
'title': title,
'url': response.url,
'extracted_links': links,
}
# 假设我们还想跟踪页面上的其他链接
for next_page_link in links:
if next_page_link is not None:
# 使用response.urljoin处理相对路径
yield response.follow(next_page_link, callback=self.parse)在上面的
parse
yield
通常,我们会定义一个
Item
items.py
# my_crawler_project/my_crawler_project/items.py
import scrapy
class MyCrawlerProjectItem(scrapy.Item):
# 定义你的数据字段
title = scrapy.Field()
url = scrapy.Field()
extracted_links = scrapy.Field()
# 还可以添加其他字段,比如发布日期、作者等然后,在你的Spider中导入并使用它:
# my_crawler_project/my_crawler_project/spiders/example_spider.py
# ...
from my_crawler_project.items import MyCrawlerProjectItem
class ExampleSpider(scrapy.Spider):
# ...
def parse(self, response):
item = MyCrawlerProjectItem()
item['title'] = response.css('h1::text').get()
item['url'] = response.url
item['extracted_links'] = response.css('a::attr(href)').getall()
yield item
# ...数据抓取后,你可能还需要对它们进行清洗、验证或存储。Scrapy的
Item Pipelines
pipelines.py
settings.py
最后,运行你的爬虫,通常在项目根目录下执行:
scrapy crawl example_spider -o output.json
-o
这只是Scrapy的冰山一角,它还有中间件、设置文件等诸多功能,让你可以精细控制爬虫的行为,处理各种复杂的场景。
在网络爬虫的世界里,反爬机制就像网站设下的迷宫,总得想办法绕过去。Scrapy本身虽然强大,但应对反爬,很多时候需要我们手动配置和一些策略。这不像有个按钮一按就搞定,更像是玩一场策略游戏,需要针对不同网站的特点来调整。
最常见也最基础的反爬,就是检查你的
User-Agent
User-Agent
User-Agent
settings.py
User-Agent
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'
User-Agent
IP限制也是个大头。网站会监控来自同一个IP的请求频率,一旦发现异常,就可能封禁这个IP。这时,代理IP池就派上用场了。你可以购买或收集一些高质量的代理IP,然后同样通过下载中间件,让Scrapy的每个请求都通过不同的代理IP发出。这块儿配置起来稍微复杂一点,涉及到代理的验证、轮换策略,甚至失败重试机制。但一旦搭建起来,效果立竿见影。
请求频率控制也是一个关键点。有些网站不会直接封IP,而是通过返回验证码或者降低响应速度来“劝退”你。Scrapy的
DOWNLOAD_DELAY
DOWNLOAD_DELAY = 2 # 每次请求间隔2秒
AUTOTHROTTLE
对于一些依赖JavaScript渲染内容的网站,Scrapy默认是无法处理的,因为它只抓取原始HTML。这时候,你就需要集成像
Scrapy-Splash
Selenium
Scrapy-Splash
Selenium
最后,遇到验证码(CAPTCHA)或者复杂的登录流程,这通常是最头疼的。简单的图片验证码可能可以接入第三方打码平台,但行为验证码、滑动验证码等就非常棘手了,很多时候需要人工介入或者更高级的机器学习模型来识别。这块儿往往是爬虫工程师最“绝望”的地方,因为这意味着你可能需要放弃一部分数据,或者投入巨大的精力去攻克。
总之,处理反爬是一个持续学习和迭代的过程,没有一劳永逸的方案。你需要根据目标网站的具体情况,灵活运用Scrapy的各种配置和扩展,甚至结合外部工具。
Scrapy抓取到的数据,最终肯定是要保存下来的,不然爬虫就白忙活了。Scrapy在数据存储和导出方面提供了相当多的灵活性,从最简单的文件输出到复杂的数据库集成,应有尽有。我个人觉得,选择哪种方式,主要看你的数据量、后续的数据处理需求以及你对数据持久化的要求。
最直接、最便捷的方式,就是直接输出到文件。Scrapy内置了多种格式的导出器:
scrapy crawl your_spider -o output.json
scrapy crawl your_spider -o output.jl
scrapy crawl your_spider -o output.csv
scrapy crawl your_spider -o output.xml
这些文件导出方式非常适合快速测试、小规模数据抓取或者作为临时存储。但对于需要频繁查询、更新或者大规模的数据,文件就不那么方便了。
这时候,数据库就成了更好的选择。Scrapy通过
Item Pipelines
Item Pipelines
关系型数据库 (如MySQL, PostgreSQL, SQLite): 这种方式非常常见。你需要在
pipelines.py
SQLAlchemy
psycopg2
mysql-connector-python
# my_crawler_project/my_crawler_project/pipelines.py
import sqlite3
class SQLitePipeline:
def __init__(self):
self.conn = sqlite3.connect('my_data.db')
self.cur = self.conn.cursor()
self.cur.execute('''
CREATE TABLE IF NOT EXISTS articles (
title TEXT,
url TEXT PRIMARY KEY,
extracted_links TEXT
)
''')
self.conn.commit()
def process_item(self, item, spider):
try:
self.cur.execute('''
INSERT INTO articles (title, url, extracted_links) VALUES (?, ?, ?)
''', (item.get('title'), item.get('url'), str(item.get('extracted_links'))))
self.conn.commit()
except sqlite3.IntegrityError: # 处理主键冲突,例如URL重复
spider.logger.warning(f"Duplicate item found: {item.get('url')}")
return item
def close_spider(self, spider):
self.conn.close()别忘了在
settings.py
ITEM_PIPELINES = {'my_crawler_project.pipelines.SQLitePipeline': 300,}NoSQL数据库 (如MongoDB, Redis): 对于非结构化或半结构化数据,NoSQL数据库可能更合适。比如MongoDB,你可以直接将Scrapy Item(本质上是字典)存储为JSON文档。同样,你需要一个对应的Python客户端库(如
pymongo
除了这些,如果你需要将数据推送到消息队列(如Kafka, RabbitMQ)进行实时处理,或者上传到云存储(如AWS S3, Google Cloud Storage),也都可以通过自定义
Item Pipelines
选择哪种存储方式,真的取决于你的具体需求。如果是为了快速验证一个想法,或者数据量不大,文件导出最省心。如果数据需要长期保存、频繁查询,或者与其他系统集成,那么数据库无疑是更专业的选择。
开发Scrapy爬虫,就像解谜一样,充满乐趣,但也难免会遇到一些让你挠头的问题。我个人在调试Scrapy时,经常会遇到一些重复性的“坑”,但好在Scrapy提供了不少趁手的工具来帮助我们排查。
常见的陷阱:
选择器(Selectors)错误: 这是最最常见的。你看着浏览器开发者工具里的XPath或CSS路径,觉得万无一失,结果爬虫跑起来就是抓不到数据。
::text
::attr()
item['field']
None
start_urls
allowed_domains
start_urls
allowed_domains
忽略robots.txt
robots.txt
robots.txt
settings.py
ROBOTS_TXT_OBEY = False
robots.txt
异步特性理解不足: Scrapy是异步的,这意味着你的
parse
yield
Request
callback
parse
反爬机制触发: 网站检测到你是爬虫,直接返回空内容、验证码、或者HTTP 403/404/500错误。
User-Agent
编码问题: 有时候,网站的编码不是UTF-8,或者响应头里没有正确声明编码,导致抓取到的中文等非ASCII字符显示为乱码。
response.encoding
趁手的调试技巧:
scrapy shell
scrapy shell
scrapy shell "http://www.example.com/some_page"
response.css()
response.xpath()
view(response)
日志(Logging): Scrapy的日志系统非常详细,默认会输出很多有用的信息,比如请求状态码、被过滤的请求等。
settings.py
LOG_LEVEL = 'DEBUG'
self.logger.info("...")self.logger.debug("...")查看下载的响应: 当你怀疑某个请求返回的内容不对劲时,可以将
response.body
# 在parse方法中
with open('debug_response.html', 'wb') as f:
f.write(response.body)这能让你直观地看到Scrapy实际接收到的页面内容,判断是抓取问题还是解析问题。
pdb
pdb
import pdb; pdb.set_trace() # 在你想设置断点的地方加入这行
dont_filter=True
Request
dont_filter=True
调试爬虫是一个经验积累的过程。多动手,多观察日志,多使用
scrapy shell
以上就是Python如何制作网络爬虫?Scrapy框架的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号