Scrapy爬虫运行无响应问题求助:爬取cinematreasures.org美国影院列表失败
解决你的Scrapy爬虫问题:无输出、代理配置与CSV导出
先从你遇到的爬虫无输出核心问题说起,我梳理了代码里的几个关键问题,这大概率是导致你爬虫静默的原因:
1. 修正URL中的转义字符错误
你的start_urls里用了&,这是HTML的转义字符,实际请求的URL里需要用原生的&。把起始URL改成:
start_urls = ['http://cinematreasures.org/theaters/united-states?page=1&status=all']
错误的转义字符会让请求的地址解析异常,自然拿不到页面内容。
2. 修复下一页链接的提取逻辑
你现在用response.xpath("//a[@class='next_page']").get()拿到的是整个<a>标签的HTML代码,而不是实际的链接地址。应该提取href属性:
next_page = response.xpath("//a[@class='next_page']/@href").get()
这样才能正确获取下一页的URL,让爬虫实现翻页爬取。
3. 配置浏览器级别的User-Agent(反爬绕过)
网站可能识别到Scrapy默认的User-Agent是爬虫,直接拒绝了请求。打开settings.py,找到DEFAULT_REQUEST_HEADERS,修改成浏览器的User-Agent,比如:
DEFAULT_REQUEST_HEADERS = { 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36' }
这也是为什么Scrapy Shell能正常运行的原因——Shell的User-Agent和你的浏览器一致,而爬虫默认的UA太容易被识别。
配置代理IP的两种实用方式
如果网站确实封了你的IP,你可以用以下两种方法配置代理:
方法1:在单个Request中直接添加代理
在parse方法生成Request时,通过meta参数指定代理:
yield scrapy.Request( response.urljoin(next_page), meta={'proxy': 'http://你的代理IP:端口'} )
如果代理需要账号密码,格式改为:
meta={'proxy': 'http://用户名:密码@你的代理IP:端口'}
方法2:用自定义中间件统一处理代理
创建一个middlewares.py文件,添加代理处理逻辑:
class ProxyMiddleware: def process_request(self, request, spider): # 固定代理 request.meta['proxy'] = 'http://你的代理IP:端口' # 如果代理需要认证,取消下面注释并填写账号密码 # from scrapy.http import Headers # import base64 # proxy_user_pass = '用户名:密码' # encoded_user_pass = base64.b64encode(proxy_user_pass.encode()).decode() # request.headers['Proxy-Authorization'] = f'Basic {encoded_user_pass}'
然后在settings.py里启用这个中间件:
DOWNLOADER_MIDDLEWARES = { '你的项目名.middlewares.ProxyMiddleware': 100, 'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110, }
用Pandas导出CSV(或直接用Scrapy自带导出)
方式1:Scrapy自带导出(最简单)
直接在命令行运行爬虫时加上导出参数,Scrapy会自动处理:
scrapy crawl listall -o theaters.csv
方式2:用Pandas手动导出(支持数据预处理)
如果需要对爬取的数据做清洗、筛选等操作,可以在爬虫里收集items,然后在爬虫关闭时用Pandas导出:
from scrapy import Spider import pandas as pd class ListallSpider(Spider): name = 'listall' allowed_domains = ['cinematreasures.org'] start_urls = ['http://cinematreasures.org/theaters/united-states?page=1&status=all'] items = [] # 用于存储所有爬取到的数据 def parse(self, response): for row in response.xpath('//table//tr')[1:]: name = row.xpath('td//text()')[2].get() address = row.xpath('td//text()')[4].get() item = {'Name': name, 'Address': address} self.items.append(item) yield item next_page = response.xpath("//a[@class='next_page']/@href").get() if next_page: yield scrapy.Request(response.urljoin(next_page)) def close(self, reason): # 爬虫关闭时导出CSV df = pd.DataFrame(self.items) df.to_csv('theaters.csv', index=False) self.logger.info('CSV文件已成功导出!')
按照上面的步骤修改后,你的爬虫应该就能正常运行、获取数据并导出CSV了。
内容的提问来源于stack exchange,提问作者Titto Charles




