Scrapy 爬豆瓣--记录

豆瓣电影爬虫实践
本文介绍了一种基于Python的Scrapy框架实现的豆瓣电影爬虫应用。该爬虫能够从豆瓣电影网站抓取热门电影的详细信息,包括片名、评分等,并通过解析JSON数据和网页内容来获取更全面的数据。文章提供了详细的代码示例和步骤说明。
# -*- coding: utf-8 -*-
import scrapy
import ConfigParser
import re

class MovieSpider(scrapy.Spider):
    download_delay = 1 #防止IP被封,设置爬取时间
    config = ConfigParser.RawConfigParser() #RawConfigParser
    config.read('douban_movie/config.ini') #读取配置文件
    tag = config.get("Section","tag") #读取配置文件中的tag,也就是需要查找的栏目,此处是热门
    limit = int(config.get("Section","limit")) #读取配置文件中的limit,URL中是20
    page = int(config.get("Section","page")) #读取返回的JSON的页数,默认是0
    name = 'movie' #爬虫名称
    allowed_domains = ['movie.douban.com'] #爬取域,设置这个只爬取指定域
    base_urls = "https://movie.douban.com/j/search_subjects?type=movie&tag=%s&sort=recommend&page_limit=%s&page_start=%s"
    start_urls = [base_urls % (tag,limit,page)]

    def parse(self, response):
        from json import loads
        infos = loads(response.body)['subjects'] #把返回的Json转换为字典类型

        for info in infos:
            meta_item = {}
            meta_item['片名'] = info['title'] #取得Json中的影片名字
            meta_item['评分'] = info['rate'] #取得评分信息

            '''把Json中的影片URL传入回调函数,并且把取出的片名和评分传入方便使用'''
            yield scrapy.Request(info['url'],meta={'_meta_item':meta_item},callback=self.parse_page)


        if len(infos) == self.limit: #判断字典长度是否与limit相等,相等则继续,不等爬虫停止
            self.page += self.limit
            url = self.base_urls % (self.tag,self.limit,self.page)

            yield scrapy.Request(url)


    def parse_page(self,response):
        meta_item = response.meta['_meta_item'] #取得传入的片名和评分

        '''取得页面中需要的所有文字信息'''
        infos = response.css('div.subject div#info').xpath('string(.)').extract_first()

        '''提取class为pl的span标签中的所有影片字段,去掉左右空格,替换掉冒号'''
        fields = [s.strip().replace(':','') for s in response.css('div#info span.pl::text').extract()]

        '''使用re.split切割infos'''
        values = [re.sub('\s+','',s.strip()) for s in re.split('\s*(?:%s):\s*' % '|'.join(fields),infos)][1:]

        '''加入字典'''
        meta_item.update(dict(zip(fields,values)))

        yield meta_item
### 使用 Scrapy 豆瓣电影和评论的教程 #### 创建 Scrapy 项目 要使用 Scrapy 开始豆瓣电影及其评论,首先需要创建一个新的 Scrapy 项目。可以通过以下命令完成此操作: ```bash scrapy startproject douban_movie_reviews ``` 这将在当前目录下生成一个名为 `douban_movie_reviews` 的新项目。 --- #### 定义 Items 数据结构 为了存储取到的数据,在项目的 `items.py` 文件中定义所需的字段。对于豆瓣电影和其评论的信息,可以参考如下代码: ```python import scrapy class MovieItem(scrapy.Item): movie_name = scrapy.Field() # 电影名称 director = scrapy.Field() # 导演 actors = scrapy.Field() # 主演 release_date = scrapy.Field() # 上映日期 rating = scrapy.Field() # 用户评分 review_count = scrapy.Field() # 总评论数 reviews = scrapy.Field() # 单条评论内容 ``` 以上代码定义了一个用于保存电影基本信息以及单条评论的内容模型[^2]。 --- #### 配置 Spider 接下来配置具体的爬虫逻辑。假设目标是从某个特定页面获取电影详情页链接并进一步提取每部电影下的用户评论,则可以在 spiders 目录下新建一个 Python 文件(如 `douban_spider.py`),其中实现主要业务逻辑。 以下是完整的爬虫脚本示例: ```python import scrapy from ..items import MovieItem class DoubanSpider(scrapy.Spider): name = "douban" allowed_domains = ["movie.douban.com"] custom_settings = { 'DOWNLOAD_DELAY': 1, # 设置下载延迟防止被封禁 IP 地址 'CONCURRENT_REQUESTS_PER_DOMAIN': 8, 'USER_AGENT': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)' } def start_requests(self): urls = [ f'https://movie.douban.com/top250?start={i * 25}' for i in range(10) ] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): movies_links = response.css('div.hd a::attr(href)').getall() for link in movies_links[:]: yield scrapy.Request(link, self.parse_movie_details) def parse_movie_details(self, response): item = MovieItem() item['movie_name'] = response.xpath('//span[@property="v:itemreviewed"]/text()').extract_first().strip(), item['director'] = ', '.join(response.xpath("//a[@rel='v:directedBy']/text()").extract()), item['actors'] = ','.join([actor.strip() for actor in response.xpath("//a[@rel='v:starring']/text()").extract()]), item['release_date'] = ''.join(response.xpath("//span[@property='v:initialReleaseDate']/text()").extract()).split('(')[0].strip(), item['rating'] = float(response.xpath("//strong[@property='v:average']/text()").extract_first()), comments_url = response.url + 'comments/' request = scrapy.Request(comments_url, callback=self.parse_comments) request.meta['item'] = item yield request def parse_comments(self, response): item = response.meta['item'] all_reviews = [] comment_blocks = response.css('.comment-item') for block in comment_blocks: username = block.css('.comment-info > a ::text').get(default='') content = block.css('.short ::text').get(default='') single_review = {'username': username, 'content': content} all_reviews.append(single_review) item['reviews'] = all_reviews next_page = response.css('#paginator .next a::attr(href)').get() if next_page is not None and len(all_reviews) < int(item.get('review_count', 0)): new_request = response.follow(next_page, callback=self.parse_comments) new_request.meta['item'] = item yield new_request else: yield item ``` 上述代码实现了从首页抓取电影列表 -> 进入具体影片页面解析元数据 -> 访问该片对应的短评区逐级加载更多评论直至全部收集完毕的整体流程[^3][^4]。 --- #### 处理反机制 由于豆瓣网站存在一定的防措施,建议采取以下策略规避风险: - **设置合理的请求间隔时间**:通过调整参数 `'DOWNLOAD_DELAY'` 来降低访问频率; - **模拟浏览器行为**:修改 User-Agent 字符串伪装成正常用户的浏览习惯; - 如果遇到验证码或其他复杂验证手段,则可能需要用到 Selenium 或 Puppeteer 结合动态渲染技术辅助解决。 --- #### 存储结果 最后一步就是决定如何持久化所获得的结果集,默认情况下会打印至终端输出流;如果想将其导出为 JSON 文件形式的话只需执行下面这条指令即可: ```bash scrapy crawl douban -o output.json ``` 这样就可以得到一份包含所有指定范围内热门影视作品连同它们底下若干精选留言记录在内的汇总文档了! ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值