【scrapy】使用方法概要(二)(转)

本文介绍了Scrapy爬虫的工作原理及其抓取流程。详细解释了Scrapy引擎、调度器、下载器、解析器等核心组件的功能,以及数据如何在各组件间流转。适合初学者了解Scrapy的基本操作。

【请初学者作为参考,不建议高手看这个浪费时间】

 

上一篇文章里介绍了scrapy的主要优点及linux下的安装方式,此篇文章将简要介绍scrapy的爬取过程,本文大部分内容源于scrapy文档,翻译并加上了笔者自己的理解。

 

忘记scrapy,一般所说的爬虫工作分为两个部分,downoader 和 parser:

downloader输入是url列表,输出抓取到的rawdata,可能时候是html源代码,也可能是json,xml格式的数据。

parser输入是第一部分输出的rawdata,根据已知的规则提取所需的info

image

图1. 简单爬虫

 

图1所示的是最简单的爬虫,不考虑解析url,并把rawdata中的url提取做进一步提取,并假设预先知道抓取的所有的url,而且抓到的网页的parser(提取规则)是相同的。

 

---------------------------------------------------------------------------------------------------------------------------

重新回到主角scrapy

下面是摘取的scrapy文档中的抓取流程图

image

官方文档中对图中的每个components如下:

scrapy engine 【scrapy引擎】

引擎控制系统中的数据流,当某些情况发生时,触发事件。

scheduler 【调度器】

调度器接受引擎发送过来的request对象【可简单理解成抓取任务】并把他们入队列,等待的引擎在适当时刻提取出这些request并把它们通过下载中间件交给downloader去做下载。

Downloader【下载器】

Downloader根据request对象中的地址获取网页内容告知引擎下载结果,并把网页内容传送给spider组件

Spiders【解析器】

Spiders是开发人员主要接触的组件,开发人员通过在这里coding,从raw网页中提取出所需的数据并存入item【数据原单元,一个item代表一项数据对象,使用者自己定义item包含的数据项】或者提取出新的抓取request对象【新的抓取任务】 一个爬虫负责一个指定domain列表下的网页

ItemPipeline【item管道】

item管道负责处理爬虫吐出的item,包括数据清理,验证,保存

DownloaderMiddleware【下载中间件】

【工作原理很像一般mvc框架中的拦截器或者behavior,开发者可以在某些步骤之间插入自己的处理逻辑】有了中间件,开发这可以在engine向downloader传request任务之间,或者,在downloader下载完毕,向engine吐回response对象的时候对request,或者resonse插入custom code

Spider milldleware【解析器中间件】

spider middleware是引擎和spider之间的hook程序【拦截器】,用来处理spider的输入【response】和输出【item and requests】

 

【这两类中间件为开发者提供了非常便利的扩展scrapy的方式】

 

image

scrapy的数据流有engine【类似于mvc框架中的controller】指挥,如下:

1. engine打开一个domain,定位spider代码的位置,获取最初的urls【start_urls,暂叫‘种子’】,拿到Request对象

2. 拿到这些最初的Request对象,并把他们交给scheduler,enqueue到scheduler负责的任务队列中

3. engine向scheduler索取下一个要下载的request【url】

4. scheduler收到请求后,从任务队列中pop出一个request,并feed给engine,engine收到后,将抓取任务发送给downloader,这些request将通过downloader middlewares【scrapy默认会开启很多内置的downloader】

5. 当downloader下载完毕后,downloader生成一个Response对象并通过downloader middlerware传递给engine

6. engine拿到reponse后,通过spidermiddleware将response交给spider做解析工作

7. spider解析response,将解析出来的item和新的Request【新的抓取任务】交给engine

8. engine将拿到的item交给pipeline处理,将新的Request按照第2步骤发送给scheduler

9. 程序会在2-8之间循环直至scheduler中的任务队列为空

喜欢一起简单,实用的东西,拒绝复杂花哨,我不是GEEK.
<think> 首先,用户的问题是:“我想查找scrapy在提取负数时出错的原因 请问scrapy提取负数出错的原因”。我需要基于提供的系统级指令来回答。 系统级指令包括: - 所有行内数学表达式必须使用$...$格式。 - 独立公式使用$$...$$格式并单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,如[^1]。 用户引用了几个参考: - 引用[1]:是关于Scrapy爬虫的代码示例,存储数据到本地。 - 引用[2]:是关于bug处理的通用方法。 - 引用[3]:是关于学习Python的动力。 - 引用[4]:是关于Python基础的概要。 用户说:“上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。” 但我没有用户上一次的问题或我的回答的上下文。所以,我需要专注于当前的问题。 当前问题:查找Scrapy在提取负数时出错的原因。 关键点:Scrapy是一个Python框架,用于网页爬取和数据提取。用户提到“提取负数时出错”,意思是当尝试提取负数(如-5)时,Scrapy的提取过程出错。 可能的原因: 1. **数据提取方法问题**:Scrapy使用CSS或XPath选择器来提取数据。如果提取负数时出错,可能是因为选择器无法正确解析或处理负数的字符串表示。 2. **数据类型问题**:提取的数据可能是字符串,如果需要数值计算或处理负数,可能需要额外的换。 3. **编码或格式化问题**:负数可能在HTML中表示为特殊字符或格式,导致选择器出错。 4. **错误处理不足**:Scrapy的回调函数中,如果没有正确处理数据类型或边界情况,可能会导致错误。 5. **Scrapy内置问题**:Scrapy的提取器可能对某些字符(如连字符)敏感。 从引用[1]中,用户提供了Scrapy爬虫的代码: ```python def parse(self, response): page = response.url.split("/")[-2] file_name = "quotes-{}.txt".format(page) with open(file_name,'w') as f: quotes = response.css(".quote") for quote in quotes: title = quote.css('.text::text').extract()[0] author = quote.css('.author::text').extract()[0] tags = quote.css('.tag::text').extract() print('title:\n',title) print('author:\n',author) print('tags:\n',tags) f.write('title:{}\n author:{}\n tags:{}\n'.format(title,author,tags)) ``` 在这个代码中,提取title和author时,使用了`.extract()[0]`。但如果提取到的文本包含负数,可能会有问题。 常见错误: - 如果负数在HTML中是特殊格式(如用--表示负号),选择器可能误解。 - 提取失败时,`.extract()[0]`会抛出IndexError如果没有匹配项。 - 数据类型:title和author是字符串,但如果内容是数字(如-5),可能需要换。 引用[2]提到bug处理:使用print()调试、检查文档、管理bug。 引用[4]提到Python数据类型:字符串处理、格式化输出。 所以,我需要构建回答: 1. **诊断原因**:解释为什么提取负数可能出错。 2. **具体建议**:基于引用提供调试和解决方法。 3. **添加引用**:自然地引用相关部分。 4. **使用中文**:整个回答都用中文。 5. **生成相关问题**:在末尾添加相关问题。 6. **格式**:遵循数学表达式规则,但这个问题可能不涉及数学,所以可能不需要LaTeX。用户的问题是文本处理,所以我应该避免不必要的数学格式。 可能的原因总结: - **选择器问题**:CSS选择器可能无法正确捕获包含负数的文本。 - **编码问题**:HTML中的负号(-)可能与特殊字符混淆。 - **提取方法**:`.extract()[0]`假设总是有匹配;如果没有匹配,会出错。 - **类型换**:如果提取后需要处理为数字,但字符串包含非数字字符。 回答结构: 1. 介绍问题:解释Scrapy提取负数时可能的错误。 2. 可能原因:列出常见原因。 3. 调试方法:基于引用[2],建议使用print调试。 4. 解决方案:如何修复代码。 5. 引用:自然地添加引用。 6. 结尾:生成相关问题。 生成相关问题: - 如何调试Scrapy的数据提取错误? - Scrapy如何处理特殊字符的提取? - 如何在Scrapy中安全地提取数值数据? 确保回答清晰、逐步解决。 </think> ### Scrapy提取负数时出错的原因分析 当使用Scrapy框架提取负数(如$-5$或$-3.14$)时,常见错误可能源于数据提取方法、数据类型换或HTML解析问题。下面我将基于您提供的引用内容,逐步分析可能的原因并提供解决方案。分析过程参考了Scrapy的文档和通用调试实践[^1][^2]。 --- ### 1. **CSS/XPath选择器问题(最常见原因)** Scrapy通过CSS或XPath选择器提取数据。如果负数在HTML中以特殊格式表示(如使用连字符"-"),选择器可能无法正确匹配文本: - **示例情况**:在HTML中,负数可能被包裹在特殊标签中(如`<span class="negative">-5</span>`),但您的选择器(如`.text::text`)忽略了嵌套结构。 - **错误表现**:`.extract()[0]`可能返回空列表或截断字符串,导致`IndexError`或提取结果缺失负号(例如输出"5"而非"-5")。 - **调试建议**:在提取代码中添加`print()`语句分段检查数据完整性[^2],如在引用[1]的代码中添加: ```python title = quote.css('.text::text').extract()[0] print("Raw title extract:", title) # 检查是否包含负号 ``` - **解决方案**:优化选择器路径,确保覆盖负号的上下文。例如: - 使用完整XPath:`response.xpath('//span[@class="negative"]/text()').extract_first()`。 - 或添加伪类处理:`.css('.text::text, .negative::text').extract_first()`。 ### 2. **数据类型换错误** 提取的数据默认为字符串类型,直接处理负数时可能引发类型错误: - **问题根源**:如果您将提取的字符串(如`"-5"`)直接用于数值计算或存储,但未显式换为数字类型(如`int`或`float`),可能导致格式错误。例如,引用[1]中的`f.write()`方法可能错误写入字符串而非数值。 - **数学表达式示例**:假设需要计算 $x - y$,但$x$和$y$均为字符串,则表达式会失败。 - **错误表现**:Python抛出`ValueError`(如无法将字符串为浮点数)或输出格式混乱(如`tags:['-5']`而非数值)。 - **调试建议**:使用`type()`函数验证数据类型[^4]: ```python raw_num = quote.css('.number::text').extract_first() print("Type of extracted data:", type(raw_num)) # 输出应为<class 'str'> ``` - **解决方案**:在写入或计算前换数据类型: ```python try: numeric_value = float(raw_num) # 换为浮点数 except ValueError: print(f"Conversion error for: {raw_num}") # 处理无效格式 ``` ### 3. **HTML编码或特殊字符冲突** 负数中的负号("-")可能与HTML实体(如`−`)混淆,或受页面编码影响: - **问题根源**:某些网站使用HTML实体表示负号(如`−`),但Scrapy的默认解析器可能将其视为普通文本,导致提取结果不完整。 - **错误表现**:提取的文本显示乱码(如"'"5")或不包含负号。 - **调试建议**:检查响应内容的原始HTML(在Scrapy Shell中运行`view(response)`),确认负号的编码格式[^2]。 - **解决方案**: - 使用Scrapy的`replace_entities`参数处理实体:`.css('.text::text').re(r'[-\d.]+')`。 - 或在下载中间件中添加编码处理:设置`FEED_EXPORT_ENCODING = 'utf-8'`。 ### 4. **边界情况处理不足** 如果负数出现在动态内容或异常结构中,选择器可能失效: - **问题根源**:引用[1]的代码假设`.extract()[0]`总是有效,但当页面结构中无匹配元素时(如负数标签缺失),会触发`IndexError`。 - **错误表现**:爬虫崩溃并输出日志错误(如`list index out of range`)。 - **解决方案**:使用`.extract_first(default='')`替代`.extract()[0]`,提供默认值: ```python title = quote.css('.text::text').extract_first("Default Value") ``` - 这避免了空列表导致的异常,并允许后续处理。 ### 通用调试步骤(基于引用[2]) 1. **分段打印(Print Debugging)**:在关键步骤插入`print()`,检查提取前后数据的变化。例如: ```python quotes = response.css(".quote") print("Number of quotes found:", len(quotes)) # 确认匹配元素数量 ``` 2. **文档查阅**:参考Scrapy官方文档的[选择器部分](https://docs.scrapy.org/en/latest/topics/selectors.html),验证语法是否正确。 3. **错误归类**:记录错误日志并归类(如使用Teambin工具),区分选择器错误或类型换问题[^2]。 4. **本地测试**:在Scrapy Shell中直接测试提取逻辑: ```bash scrapy shell "http://example.com" >>> response.css('.negative::text').get() ``` 通过以上方法,多数负数提取错误可解决。核心原则是:**确保选择器覆盖负号上下文、显式换数据类型,并添加健壮的错误处理**。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值