1
0

Python: Scrapy 实践

This commit is contained in:
周中平 2024-10-16 11:42:31 +08:00
parent 8551d5d3e8
commit aa355b3658
Signed by: zhouzhongping
GPG Key ID: 6666822800008000

View File

@ -1469,3 +1469,323 @@ Scrapy 项目的配置文件(`settings.py`)集中管理了所有与爬虫行
from .settings_base import * from .settings_base import *
DOWNLOAD_DELAY = 0.5 DOWNLOAD_DELAY = 0.5
``` ```
## 实战案例分析
通过实际项目的分析与实践,可以更好地理解如何将 Scrapy 用于解决现实中的数据抓取问题。本节将通过电商网站的数据采集示例,展示如何进行爬虫设计、数据存储及分析。
### 电商网站数据采集
电商网站上通常包含产品名称、价格、库存、评价等关键信息,这些数据对市场分析、竞品研究有重要的参考价值。我们将以模拟电商网站为例,展示如何通过 Scrapy 实现数据采集,并将其存储与分析。
#### 项目需求与目标
**需求与目标:**
- 抓取某电商网站的产品信息,包括产品名称、价格、库存、评价数、产品详情页链接等。
- 实现定期抓取,分析产品价格变化趋势,并进行竞品比价。
- 需要将数据存储到数据库或导出为 CSV 文件,以便后续数据分析和可视化。
**具体数据抓取字段:**
- 产品名称name
- 价格price
- 库存stock
- 评价数reviews
- 产品详情页链接url
#### **爬虫设计与实现**
**目标网站:** 我们以模拟的电商网站 http://books.toscrape.com/ 为例,这是一个包含书籍商品信息的示例网站,页面包含产品名称、价格、库存等信息,非常适合做数据抓取示例。
1. **创建 Scrapy 项目**:首先,我们创建一个 Scrapy 项目,用于抓取数据:
```shell
scrapy startproject ecommerce_spider
```
2. **生成 Spider**在生成的项目中,使用 `scrapy genspider` 命令来创建一个名为 `book_spider` 的爬虫:
```shell
scrapy genspider book_spider books.toscrape.com
```
3. **编写 Spider** 创建 Spider 并定义数据抓取逻辑。我们将抓取书籍的名称、价格、库存、评价数等信息。
```python
import scrapy
class BookSpider(scrapy.Spider):
name = 'book_spider'
start_urls = ['http://books.toscrape.com/']
def parse(self, response):
# 解析每本书的信息
for book in response.css('article.product_pod'):
yield {
'name': book.css('h3 a::attr(title)').get(),
'price': book.css('div.product_price p.price_color::text').get(),
'stock': book.css('p.instock.availability::text').re_first('\d+'),
'reviews': book.css('p.star-rating::attr(class)').re_first('star-rating (\w+)'),
'url': response.urljoin(book.css('h3 a::attr(href)').get()), # 完整的 URL
}
# 处理分页
next_page = response.css('li.next a::attr(href)').get()
if next_page:
yield response.follow(next_page, self.parse)
```
**解释:**
- 我们通过 CSS 选择器提取需要的信息,如书名、价格、库存情况、星级评测等。
- `response.urljoin()` 用于生成书籍详情页的完整链接。
- 分页处理:如果存在“下一页”,通过 `response.follow()` 方法继续抓取下一页的内容。
1. **运行爬虫并保存数据** 通过以下命令运行爬虫并将数据保存到 CSV 文件中:
```shell
scrapy crawl book_spider -o books.csv
```
爬虫会自动抓取整个网站的书籍数据并保存为 CSV 文件,便于后续的数据分析。
#### 数据存储与分析
爬取的数据可以存储到 CSV 文件、数据库(如 MySQL、MongoDB或其他格式中。这里我们将数据保存到 MySQL 数据库中。
**将数据存储到 MySQL**
1. 安装 MySQL 依赖:
```shell
pip install pymysql
```
2. 在 Scrapy 中定义数据管道,将抓取的数据保存到数据库中。
```python
import pymysql
import re
class MySQLPipeline:
def open_spider(self, spider):
self.connection = pymysql.connect(
host='localhost',
user='root',
password='password', # 修改为您的数据库密码
db='ecommerce_db', # 请确保数据库已存在
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor
)
self.cursor = self.connection.cursor()
def close_spider(self, spider):
self.connection.close()
def process_item(self, item, spider):
# 清洗价格字段,移除货币符号并转换为浮点数
if 'price' in item:
item['price'] = re.sub(r'[^\d.]', '', item['price']) # 移除非数字字符(如£)
item['price'] = float(item['price']) if item['price'] else 0.0
# 插入到 MySQL 数据库
sql = """
INSERT INTO products (name, price, stock, reviews, url)
VALUES (%s, %s, %s, %s, %s)
"""
# 为了处理库存的空值,确保 stock 是整数类型
stock = item.get('stock')
if stock is None:
stock = 0
# 插入数据
self.cursor.execute(sql, (
item['name'],
item['price'],
stock,
item['reviews'],
item['url']
))
self.connection.commit()
return item
```
3. **启用 Pipeline**
`settings.py` 中启用 MySQL Pipeline
```python
ITEM_PIPELINES = {
'ecommerce_spider.pipelines.MySQLPipeline': 300,
}
```
4. 创建 MySQL 数据库和表。
```mysql
CREATE DATABASE ecommerce_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE ecommerce_db;
CREATE TABLE products (
id INT AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INT DEFAULT 0,
reviews VARCHAR(50),
url VARCHAR(2083)
);
```
5. **运行爬虫并保存数据** 通过以下命令运行爬虫并将数据保存到数据库中,爬虫会自动抓取整个网站的书籍数据并保存到数据库,便于后续的数据分析。
```shell
scrapy crawl book_spider
```
6. 接下来,我们使用 Pandas 对数据进行分析,并使用 Matplotlib 进行可视化。
```shell
# 安装依赖
pip install pandas matplotlib sqlalchemy
```
```python
# 分析价格变化趋
import pandas as pd
import matplotlib.pyplot as plt
from sqlalchemy import create_engine
# 创建数据库连接
engine = create_engine('mysql+pymysql://root:password@localhost/ecommerce_db')
# 读取数据到 DataFrame
df = pd.read_sql('SELECT * FROM products', con=engine)
# 进行价格分析和可视化
print(df['price'].describe())
# 可视化价格分布
df['price'].hist(bins=20)
plt.xlabel('Price (£)')
plt.ylabel('Number of Books')
plt.title('Price Distribution of Books')
plt.grid(axis='y')
plt.show()
```
通过 Pandas 可以轻松实现数据的统计、清洗和可视化,后续可以进一步进行竞品分析或趋势预测。
### 社交媒体数据抓取
社交媒体平台提供了大量实时数据,包括用户发布的动态、评论、点赞等,这些数据可以用于舆情监控、市场分析、广告效果评估等。然而,社交媒体通常会有较强的反爬机制,需要采用特殊的策略。
#### 反爬策略的应对
社交媒体网站通常采用如下反爬策略:
- **频繁的 IP 封禁**:检测过高的请求频率并封禁 IP。
- **强制登录**:很多内容只能登录后访问。
- **动态加载**:许多数据通过 JavaScript 加载或 AJAX 请求动态更新。
**应对策略:**
- **使用代理 IP 池**:通过不断切换 IP 来分散请求。
- **模拟登录与会话保持**:使用 Selenium 或 Scrapy 的 `FormRequest` 模拟登录并保持会话。
- **处理动态加载**:可以使用 Selenium 或 Splash 处理 JavaScript 渲染。
#### 实时数据的抓取与更新
社交媒体数据通常是动态、实时更新的,因此需要定期抓取并更新数据。
```python
# 实时抓取推特上的特定关键词(示例)
import scrapy
from scrapy_selenium import SeleniumRequest
class TwitterSpider(scrapy.Spider):
name = 'twitter_spider'
start_urls = ['https://twitter.com/search?q=python&src=typed_query']
def start_requests(self):
for url in self.start_urls:
yield SeleniumRequest(url=url, callback=self.parse)
def parse(self, response):
tweets = response.css('div.css-901oao')
for tweet in tweets:
yield {
'user': tweet.css('span.username::text').get(),
'content': tweet.css('div.tweet-text::text').get(),
'time': tweet.css('a.tweet-timestamp::attr(title)').get(),
}
```
通过 Scrapy-Selenium 集成,可以处理 Twitter 页面上的 JavaScript 渲染并抓取最新的推文。
### 新闻资讯聚合爬虫
新闻聚合爬虫用于从多个新闻源抓取信息,并将不同来源的新闻汇总处理。由于不同网站的结构差异较大,爬虫需要具备处理多源异构数据的能力。
#### 多源异构数据的处理
当抓取来自不同新闻源的数据时,页面结构往往各异。因此,我们需要为不同的网站编写相应的解析逻辑,同时保证抓取的数据结构统一。
```python
class NewsSpider1(scrapy.Spider):
name = 'news_spider_1'
start_urls = ['http://example-news-site1.com']
def parse(self, response):
for article in response.css('div.article'):
yield {
'title': article.css('h1::text').get(),
'content': article.css('div.content::text').get(),
'source': 'Site1'
}
class NewsSpider2(scrapy.Spider):
name = 'news_spider_2'
start_urls = ['http://example-news-site2.com']
def parse(self, response):
for article in response.css('div.news'):
yield {
'title': article.css('h2::text').get(),
'content': article.css('p.summary::text').get(),
'source': 'Site2'
}
```
通过编写不同的爬虫来处理不同新闻网站的页面结构,但最终输出的数据格式是统一的。
#### 数据清洗与内容分析
抓取到的新闻数据可能包含广告、无关内容或重复信息,因此需要进行数据清洗。可以使用正则表达式、关键词过滤等方法去除无关数据,并通过自然语言处理技术进行内容分析。
```python
# 清洗新闻数据并进行关键词提取
import re
from collections import Counter
import pandas as pd
def clean_text(text):
text = re.sub(r'\s+', ' ', text) # 去除多余空白
text = re.sub(r'[^\w\s]', '', text) # 去除标点符号
return text.lower()
# 加载数据
df = pd.read_csv('news.csv')
# 清洗数据
df['cleaned_content'] = df['content'].apply(clean_text)
# 提取关键词
all_words = ' '.join(df['cleaned_content']).split()
word_freq = Counter(all_words)
print(word_freq.most_common(10))
```
通过数据清洗和分析,可以提取出新闻中的关键趋势和话题。