Scrapy爬虫语法错误及CSV输出异常问题求助
Scrapy爬虫问题修复与优化方案
1. 语法错误修复
你代码里的"f.write("{},{},{}\n".format(word,url,count))"这行存在双引号嵌套冲突,外层双引号和内部双引号语法冲突,直接去掉外层的双引号即可:
f.write("{},{},{}\n".format(word, url, count))
同理,代码里的"f = open('wordlist.csv', 'w')"也是多余的引号包裹,直接删除外层引号。
2. CSV文件输出问题解决
当前代码的CSV逻辑存在多处致命问题:
- 文件覆盖:每次用
open('wordlist.csv', 'w')打开文件都会清空原有内容,最终只保留最后一次爬取的数据; - 变量重置:
word_counts被放在关键词循环内部,每次循环都会被重置为空字典,只能保存最后一个关键词的统计结果; - 逻辑冗余:空列表
links的遍历完全无效,重复的关键词统计代码无意义,count多次被重置为0导致统计结果错误。
标准解决方案:用Scrapy Item+Feed输出
这是Scrapy官方推荐的结构化数据输出方式,避免手动操作文件的各种问题:
- 在爬虫文件中定义Item类
from scrapy.item import Item, Field class WordCountItem(Item): keyword = Field() url = Field() count = Field()
- 在
settings.py中配置Feed输出
FEED_URI = 'wordlist.csv' FEED_FORMAT = 'csv' FEED_EXPORT_FIELDS = ['keyword', 'url', 'count'] FEED_EXPORT_ENCODING = 'utf-8'
配置后Scrapy会自动帮你处理CSV的写入、编码和结构化格式,无需手动打开文件。
3. 爬取不全问题处理
- 域名限制:当前
allowed_domains = ["www.example.com"]仅允许爬取单个域名,若要爬取300个网站,直接删除该配置(无需限制域名),或添加所有目标域名; - 禁用requests库:代码中
requests.get(link)会阻塞Scrapy的异步请求,导致爬取效率极低甚至失败,完全不符合Scrapy的异步架构,直接删除该部分代码; - 规则优化:当前
Rule(LinkExtractor(), follow=True, callback="check_buzzwords")会跟进所有链接,可能导致爬取范围失控,可通过LinkExtractor(allow=r'正则规则')指定需要爬取的链接格式; - 移除响应过滤:自定义的
_requests_to_follow方法会过滤掉无编码的响应,建议删除该方法,使用Scrapy默认的请求跟进逻辑。
完整重构后的爬虫代码
from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor from scrapy.item import Item, Field import re # 定义结构化Item class WordCountItem(Item): keyword = Field() url = Field() count = Field() def count_keyword_occurrences(string, sub): # 直接返回关键词出现次数,无需返回所有位置 return len([match.start() for match in re.finditer(re.escape(sub), string)]) class FirstSpider(CrawlSpider): name = "FirstSpider" # 删除allowed_domains,允许爬取所有域名(按需调整) start_urls = ["https://www.example.com/"] # 替换为你的300个网站列表 rules = [ Rule(LinkExtractor(), follow=True, callback="check_buzzwords") ] crawl_count = 0 total_words_found = 0 def check_buzzwords(self, response): self.__class__.crawl_count += 1 wordlist = ["keyword1","keyword2","keyword3"] url = response.url page_content = response.text # 自动处理编码,无需手动decode for word in wordlist: count = count_keyword_occurrences(page_content, word) if count > 0: self.__class__.total_words_found += count # 生成Item,交给Scrapy自动写入CSV item = WordCountItem() item['keyword'] = word item['url'] = url item['count'] = count yield item
使用说明
- 将上述代码保存到爬虫文件中
- 在
settings.py配置好Feed输出(如前文配置) - 运行爬虫:
scrapy crawl FirstSpider,Scrapy会自动生成符合要求的wordlist.csv文件
内容的提问来源于stack exchange,提问作者hardy5050
相关产品推荐
相关产品推荐

