使用 Scrapy 抓取网页数据

1. Scrapy 简介

Scrapy 是一个流行的 Python 爬虫框架,提供了强大的工具和灵活的扩展机制,用于高效抓取和处理网页数据。它支持异步 I/O,速度快且资源消耗低,非常适合大规模爬取任务。


2. 安装 Scrapy

确保你的 Python 环境版本在 3.7 或以上。

使用 pip 安装:

pip install scrapy

验证安装:

scrapy version


3. 创建 Scrapy 项目

创建一个新的 Scrapy 项目:

scrapy startproject myproject

目录结构:

myproject/
    scrapy.cfg
    myproject/
        __init__.py
        items.py
        middlewares.py
        pipelines.py
        settings.py
        spiders/
            __init__.py

4. 编写第一个爬虫

进入项目目录并生成爬虫:

scrapy genspider example example.com

生成的文件 spiders/example.py

import scrapy

class ExampleSpider(scrapy.Spider):
    name = 'example'
    allowed_domains = ['example.com']
    start_urls = ['http://example.com']

    def parse(self, response):
        self.log('Visited: ' + response.url)

运行爬虫:

scrapy crawl example


5. 提取数据:XPath 与 CSS 选择器

Scrapy 支持 XPath 和 CSS 选择器用于解析 HTML。以下是两种选择器的简单对比:

XPath 示例:

titles = response.xpath('//h1/text()').getall()

CSS 示例:

titles = response.css('h1::text').getall()

常用方法:

  • get(): 获取单个匹配的内容。
  • getall(): 获取所有匹配的内容。
  • extract_first(): 等价于 .get()
  • extract(): 等价于 .getall()

6. 保存数据

Scrapy 支持将数据导出为 JSON、CSV、XML 等格式。

在终端中导出数据:

scrapy crawl example -o output.json

将数据存储到管道: 编辑 pipelines.py 文件:

class MyProjectPipeline:

    def process_item(self, item, spider):

        with open('output.txt', 'a') as f:

            f.write(str(item) + '\n')

        return item

settings.py 中启用管道:

ITEM_PIPELINES = { 'myproject.pipelines.MyProjectPipeline': 300, }


7. 处理动态加载的页面

许多现代网站使用 JavaScript 动态渲染内容,Scrapy 默认无法处理这种情况。可以结合以下工具:

Scrapy-Splash:

  • 安装:

    pip install scrapy-splash

  • 配置: 在 settings.py 中添加:
    SPLASH_URL = 'http://localhost:8050'
    DOWNLOADER_MIDDLEWARES = {
        'scrapy_splash.SplashCookiesMiddleware': 723,
        'scrapy_splash.SplashMiddleware': 725,
        'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,
    }
    DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'
    
  • 示例代码:
    from scrapy_splash import SplashRequest
    
    class ExampleSpider(scrapy.Spider):
        name = 'example'
        start_urls = ['http://example.com']
    
        def start_requests(self):
            for url in self.start_urls:
                yield SplashRequest(url, self.parse, args={'wait': 3})
    
        def parse(self, response):
            self.log(response.text)
    

Playwright:

  • 安装:

    pip install scrapy-playwright

  • 示例代码:
    class ExampleSpider(scrapy.Spider):
        name = 'example'
    
        def start_requests(self):
            yield scrapy.Request(
                url='http://example.com',
                meta={'playwright': True}
            )
    
        def parse(self, response):
            self.log(response.text)
    

    8. 反爬策略与解决方法
  • 设置 User-Agent:settings.py 中添加:

    USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'

  • 处理 Cookies: Scrapy 支持自动管理 Cookies,也可以手动设置:

    yield scrapy.Request(url, cookies={'key': 'value'})

  • 请求头伪装:

    headers = {

        'User-Agent': 'Your User-Agent',

        'Referer': 'http://example.com'

    }

    yield scrapy.Request(url, headers=headers)

  • 降低爬取速度:

    DOWNLOAD_DELAY = 2


9. 进阶技巧
  • 多层解析: 如果页面需要多次请求:

    def parse(self, response): 
        links = response.xpath('//a/@href').getall() 
        for link in links: 
            yield response.follow(link, self.parse_detail) 
    def parse_detail(self, response): 
        self.log(response.url)
  • 使用代理:

    PROXY = 'http://your_proxy'

    yield scrapy.Request(url, meta={'proxy': PROXY})

  • 分布式爬取: 使用 Scrapy + Redis 实现分布式爬虫。


10. 调试与测试
  • 调试 XPath 或 CSS: 在浏览器开发者工具的 Console 中测试:

    $x('//h1/text()') // XPath

    document.querySelectorAll('h1') // CSS

  • Scrapy Shell: 启动交互式调试:

    scrapy shell 'http://example.com'

11. 总结

Scrapy 是一个非常强大的爬虫框架,适合从简单的静态页面到复杂的动态加载内容的抓取需求。通过不断优化爬虫的结构和策略,可以更高效地完成数据采集任务。

  • 多层解析: 如果页面需要多次请求:

    def parse(self, response):
        links = response.xpath('//a/@href').getall()
        for link in links:
            yield response.follow(link, self.parse_detail)
    
    def parse_detail(self, response):
        self.log(response.url)
    
  • 使用代理:

    PROXY = 'http://your_proxy'

    yield scrapy.Request(url, meta={'proxy': PROXY})

  • 分布式爬取: 使用 Scrapy + Redis 实现分布式爬虫。

  • 调试 XPath 或 CSS: 在浏览器开发者工具的 Console 中测试:

    // XPath document.querySelectorAll('h1') // CSS

    $x('//h1/text()')

  • Scrapy Shell: 启动交互式调试:

    scrapy shell 'http://example.com'

### 使用 Scrapy 框架抓取网页数据 #### 创建项目 为了启动一个新的Scrapy项目,需执行命令`scrapy startproject project_name`。这将创建一个名为 `project_name` 的目录结构,其中包含了项目的配置文件和其他初始化设置。 #### 定义 Item 类型 定义要抓取的信息类型是必要的一步。对于具体应用如抓取某品会的纸尿裤数据,可以通过如下方式定义Item类[^4]: ```python import scrapy class DiaperItem(scrapy.Item): diaper_name = scrapy.Field() # 纸尿裤商品名称 diaper_price = scrapy.Field() # 价格 diaper_url = scrapy.Field() # 详情路径 diaper_source_shop = scrapy.Field(default="某品会") # 来源商城,默认为某品会 ``` #### 编写 Spider 文件 编写Spider脚本来指定起始URL以及如何解析页面内容。例如,在解析详情页时,可以利用BeautifulSoup库来处理HTML文档并从中抽取所需信息[^2]: ```python from bs4 import BeautifulSoup import scrapy def parse_detail(self, response): soup = BeautifulSoup(response.body, 'html.parser') item = zyjItem() try: item['title'] = soup.find('h1').text.strip() item['source'] = "example.com" item['author'] = soup.select_one('.author').text if soup.select_one('.author') else "N/A" item['time'] = soup.select_one('.publish-time').text if soup.select_one('.publish-time') else "N/A" item['content'] = "\n".join([p.text for p in soup.select('.article-content p')]) creator_info = soup.select_one('.creator-info') photographer_info = soup.select_one('.photographer-info') reviewer_info = soup.select_one('.reviewer-info') item['creator'] = creator_info.text if creator_info else "N/A" item['photographer'] = photographer_info.text if photographer_info else "N/A" item['reviewer'] = reviewer_info.text if reviewer_info else "N/A" except Exception as e: print(f"Parsing failed: {e}") item['error_message'] = str(e) yield item ``` #### 设置 Items Pipeline 为了让被抓取数据能够被持久化存储至MySQL或其他数据库中,需要配置Items Pipelines。此过程涉及修改settings.py文件以激活自定义pipeline,并实现相应的逻辑用于连接数据库并将items存入表内[^1]。 #### 动态加载页面支持 面对由JavaScript动态渲染的内容,Selenium是一个可行的选择。它允许模拟浏览器行为从而获取完整的DOM树。结合Scrapy使用时,通常会在中间件层面上集成这两个工具,以便于在请求前先让Selenium完成页面加载工作[^3].
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值