You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动