兄弟姐妹,大家好哇!我是喔的嘛呀。今天我们来学习 scrapy的第三部分。
目录
一、命令行工具与扩展(Command Line Tools & Extensions)
一、命令行工具与扩展(Command Line Tools & Extensions)
命令行工具与扩展(Command Line Tools & Extensions)在Scrapy爬虫框架中起着至关重要的作用。下面将详细解释如何使用Scrapy的命令行工具来创建项目、生成爬虫和启动爬虫,以及深入了解Scrapy的扩展机制,包括如何使用现有的扩展和编写自定义扩展来增强爬虫功能。
命令行工具
Scrapy提供了一套强大的命令行工具,这些工具使得创建、管理和运行爬虫项目变得简单而高效。
- 创建项目
使用scrapy startproject
命令可以创建一个新的Scrapy项目。例如:
bash复制代码
scrapy startproject myproject
这将在当前目录下创建一个名为myproject
的新目录,其中包含Scrapy项目的默认结构,如spiders
文件夹用于存放爬虫文件,以及项目的配置文件settings.py
等。
- 生成爬虫
在创建了项目之后,可以使用scrapy genspider
命令来生成新的爬虫。例如:
bash复制代码
scrapy genspider myspider example.com
这将在spiders
文件夹下生成一个名为myspider.py
的爬虫文件,其中包含了基本的爬虫结构和示例代码。你可以在这个文件中定义爬取规则、提取数据等。
- 启动爬虫
完成爬虫的编写后,使用scrapy crawl
命令来启动爬虫并开始抓取数据。例如:
bash复制代码
scrapy crawl myspider
这将启动名为myspider
的爬虫,并根据你在爬虫文件中定义的规则开始抓取数据。Scrapy还提供了其他命令,如scrapy list
来列出项目中所有的爬虫,scrapy shell
来进入交互式调试环境等。
扩展与插件
Scrapy的扩展机制是其灵活性和可扩展性的重要体现。通过扩展和插件,你可以轻松地增强爬虫的功能,满足特定的需求。
- 了解Scrapy的扩展机制
Scrapy的扩展机制主要依赖于中间件(Middleware)和信号(Signals)。中间件允许你在Scrapy引擎和组件之间插入自定义代码,以修改请求、响应或处理异常。信号则是一种事件驱动机制,你可以在Scrapy的特定阶段触发事件并处理相应的逻辑。
5. 使用现有的扩展
Scrapy社区提供了许多现成的扩展,这些扩展可以直接集成到你的爬虫项目中。例如,有些扩展可以帮助你处理反爬虫机制,如自动设置请求头、处理Cookie等;有些扩展可以优化爬虫的性能,如控制并发请求数、设置代理等。你可以通过查阅Scrapy的官方文档或社区资源,找到适合你的扩展并按照说明进行安装和配置。
- 编写自定义的扩展
如果现有的扩展无法满足你的需求,你可以编写自定义的扩展来扩展Scrapy的功能。编写自定义扩展需要一定的编程技能和对Scrapy框架的深入理解。你可以通过继承Scrapy提供的基类,并实现相应的方法来处理特定的逻辑。例如,你可以编写一个自定义的中间件来处理特定的请求头或响应数据,或者编写一个自定义的Item Pipeline来处理爬取到的数据。
编写自定义扩展时,需要注意以下几点:
- 确定你的扩展属于哪种类型(如中间件、信号处理器等)。
- 继承相应的基类并实现必要的方法。
- 在项目的设置文件中启用你的扩展。
- 测试你的扩展以确保其正常工作并与Scrapy的其他组件兼容。
通过学习和使用Scrapy的命令行工具和扩展机制,你将能够更加高效地创建、管理和扩展你的爬虫项目,实现更复杂的抓取任务和数据处理需求。
二. 爬虫优化与反反爬虫策略
爬虫优化
-
减少请求次数
可以通过合并请求、使用缓存、避免重复请求等方式来减少请求次数。例如,在Scrapy中,可以通过使用
LinkExtractors
和Rule
来定义爬虫跟随的链接规则,避免不必要的请求。from scrapy.linkextractors import LinkExtractor from scrapy.spiders import CrawlSpider, Rule class MySpider(CrawlSpider): name = 'myspider' allowed_domains = ['example.com'] start_urls = ['<http://example.com>'] rules = ( Rule(LinkExtractor(allow=r'/category/'), callback='parse_item', follow=True), ) def parse_item(self, response): # 解析页面数据 pass
-
降低网络延迟
使用连接池和异步IO可以显著降低网络延迟。Scrapy默认使用异步IO和连接池,但你也可以通过调整设置来进一步优化。
# settings.py CONCURRENT_REQUESTS = 100 # 同时发出的请求数 DOWNLOAD_DELAY = 1 # 请求之间的延迟,单位为秒 REACTOR_THREADPOOL_MAXSIZE = 20 # 线程池大小
-
提高解析速度
使用lxml代替正则表达式可以大大提高解析速度。
from scrapy.selector import Selector def parse(self, response): # 使用XPath或CSS选择器解析数据 titles = response.xpath('//h1/text()').getall() # ...
反反爬虫策略
-
设置User-Agent
在Scrapy中,可以通过设置
DEFAULT_REQUEST_HEADERS
来定义默认的User-Agent。# settings.py DEFAULT_REQUEST_HEADERS = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3' }
-
使用代理
可以使用中间件来设置代理。以下是一个简单的代理中间件示例:
class ProxyMiddleware(object): def process_request(self, request, spider): request.meta['proxy'] = "http://your_proxy_address:port"
然后在settings中启用该中间件:
# settings.py DOWNLOADER_MIDDLEWARES = { 'myproject.middlewares.ProxyMiddleware': 100, }
-
处理验证码
对于验证码,可以通过Selenium模拟用户行为来绕过。但请注意,Selenium的使用可能会降低爬虫的效率。
from selenium import webdriver from selenium.webdriver.common.keys import Keys # 初始化WebDriver driver = webdriver.Chrome() driver.get('<http://example.com>') # 模拟用户操作,如点击、输入等 captcha_input = driver.find_element_by_id('captcha-input') captcha_input.send_keys('captcha_text') captcha_input.send_keys(Keys.RETURN) # 获取页面内容并关闭WebDriver content = driver.page_source driver.quit()
-
遵守robots.txt
Scrapy默认遵守robots.txt,但你也可以通过设置
ROBOTSTXT_OBEY
来关闭这一行为。# settings.py ROBOTSTXT_OBEY = True # 遵守robots.txt,设置为False则不遵守
-
模拟用户行为
在Scrapy中,可以通过设置请求间的下载延迟来模拟用户行为。
# settings.py DOWNLOAD_DELAY = 3 # 每两个请求之间的下载延迟,单位为秒
这些策略并不是孤立的,通常需要根据目标网站的反爬虫机制来组合使用。同时,要注意合法合规地爬取数据,遵守目标网站的robots.txt协议,并尊重网站的版权和使用条款
三、数据存储与数据输出
数据存储
1. 数据库存储 - 使用SQLite
SQLite是一个轻量级的文件型数据库,不需要单独安装,可以直接在Python中使用。
import sqlite3
# 连接到SQLite数据库(如果不存在则创建)
conn = sqlite3.connect('my_database.db')
c = conn.cursor()
# 创建一个表
c.execute('''CREATE TABLE IF NOT EXISTS my_table
(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER)''')
# 假设我们有一些爬取的数据
data = [('Alice', 25), ('Bob', 30)]
# 插入数据
c.executemany('''INSERT INTO my_table (name, age) VALUES (?, ?)''', data)
# 提交事务
conn.commit()
# 关闭连接
conn.close()
2. 文件存储 - 使用JSON
JSON是一种常用的数据交换格式,可以很容易地将数据写入文件并再次读取。
import json
# 假设我们有一些爬取的数据
data = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
# 将数据写入JSON文件
with open('output.json', 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
# 从JSON文件中读取数据
with open('output.json', 'r', encoding='utf-8') as f:
loaded_data = json.load(f)
print(loaded_data)
数据输出
1. JSON格式输出
import json
# 假设我们有一些爬取的数据
data = [{'name': 'Alice', 'age': 25}, {'name': 'Bob', 'age': 30}]
# 将数据转换为JSON格式的字符串
json_data = json.dumps(data, ensure_ascii=False, indent=4)
# 打印JSON数据
print(json_data)
# 将JSON数据写入文件
with open('output.json', 'w', encoding='utf-8') as f:
f.write(json_data)
2. CSV格式输出
import csv
# 假设我们有一些爬取的数据
data = [['Alice', 25], ['Bob', 30]]
# 定义CSV文件的列名
fieldnames = ['name', 'age']
# 将数据写入CSV文件
with open('output.csv', 'w', newline='', encoding='utf-8') as csvfile:
writer = csv.writer(csvfile)
# 写入列名
writer.writerow(fieldnames)
# 写入数据行
for row in data:
writer.writerow(row)
注意:
- 在实际应用中,你可能需要处理更复杂的数据结构和异常情况。
- 对于大型数据集,直接写入文件或数据库可能会导致内存问题。在这种情况下,你可能需要使用流式处理或分批写入的方法。
- 安全性也是一个需要考虑的因素。当存储敏感信息时,确保对数据进行适当的加密和匿名化处理。
- 根据你的具体需求,你可能还需要考虑数据的索引、查询性能、并发控制等因素,特别是在使用数据库时。
四、 调试与日志(Debugging & Logging)
调试Scrapy爬虫
Scrapy 提供了一套强大的工具来帮助你调试爬虫。以下是一些常用的调试方法:
- 使用Scrapy ShellScrapy Shell 是一个交互式终端,允许你快速测试XPath或CSS选择器,以及查看页面的响应内容。
scrapy shell '<http://example.com>'
在Shell中,你可以使用 response
对象来访问页面的内容,并使用 fetch
方法获取新的页面。
-
查看异常和错误
当爬虫遇到错误时,Scrapy 会记录异常信息。你可以在终端中查看这些错误信息,并根据它们进行调试。
-
设置断点
在你的爬虫代码中,你可以使用Python的
pdb
模块或IDE(如PyCharm)来设置断点,然后逐步执行代码以查看问题所在。 -
打印调试信息
在代码中添加
print
语句可以帮助你查看变量的值或代码的执行流程。
def parse(self, response):
print(response.text) # 打印响应内容
# ... 其他代码 ...
5、使用Scrapy的日志系统Scrapy的日志系统可以帮助你记录不同级别的信息,从DEBUG到ERROR。你可以通过配置日志级别来查看更详细的信息。
日志记录
Scrapy 使用Python的内置 logging
模块进行日志记录。你可以通过修改Scrapy的设置来配置日志系统。
- 修改Scrapy的日志级别在Scrapy的设置文件中(通常是
settings.py
),你可以设置LOG_LEVEL
来改变日志的级别。
LOG_LEVEL = 'DEBUG' # 可以是 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
2、自定义日志处理器你还可以添加自定义的日志处理器来记录日志到文件或其他地方。
from scrapy import logformatter
from scrapy.utils.log import configure_logging
from logging.handlers import RotatingFileHandler
# 配置日志记录到文件
LOG_FILE = 'scrapy.log'
logging.basicConfig(
level=logging.DEBUG,
format='%(asctime)s [%(levelname)s] %(message)s',
handlers=[
RotatingFileHandler(LOG_FILE, maxBytes=1024*1024, backupCount=5),
logging.StreamHandler(),
]
)
configure_logging(install_root_handler=False)
3、在代码中记录日志在你的爬虫或中间件代码中,你可以使用 self.logger
来记录日志。
class MySpider(scrapy.Spider):
name = 'myspider'
def parse(self, response):
self.logger.info('Parsing page %s', response.url)
# ... 其他代码 ...
4、使用日志格式化器Scrapy 允许你自定义日志消息的格式。你可以修改 LOG_FORMAT
和 LOG_DATEFORMAT
设置来改变格式。
LOG_FORMAT = '%(asctime)s [%(levelname)s] %(message)s'
LOG_DATEFORMAT = '%Y-%m-%d %H:%M:%S'
通过结合使用这些调试和日志记录方法,你可以更有效地跟踪和解决Scrapy爬虫中的问题。记得在调试完成后,将日志级别设置回一个更合适的级别(如INFO),以避免记录过多的不必要信息。
好了,今天的学习就到这里啦。我们明天再见啦