1. 基于Scrapy库的爬虫架构设计
数据抓取
- 创建Scrapy项目:使用
scrapy startproject news_crawler
命令创建一个新的Scrapy项目。
- 定义Spider:在
spiders
目录下创建一个或多个Spider类,例如NewsSpider
。在Spider类中定义起始URL列表start_urls
,并实现parse
方法来处理下载的页面。
import scrapy
class NewsSpider(scrapy.Spider):
name = 'news'
start_urls = [
'http://example.com/news',
'http://another-example.com/news'
]
def parse(self, response):
# 后续在此处理页面
pass
数据解析
- XPath或CSS选择器:使用XPath或CSS选择器来定位新闻标题、正文、发布时间等信息。例如,假设新闻标题在
<h1 class="news-title">
标签中,可以使用CSS选择器response.css('.news-title::text').get()
获取标题文本。
- 正则表达式:对于一些复杂的文本提取场景,可能需要使用正则表达式。例如,从一段包含时间的文本中提取发布时间。
import re
class NewsSpider(scrapy.Spider):
#...
def parse(self, response):
title = response.css('.news-title::text').get()
time_pattern = re.compile(r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})')
time_text = response.css('.news-time::text').get()
publish_time = re.search(time_pattern, time_text).group(1) if time_text else None
yield {
'title': title,
'publish_time': publish_time
}
数据存储
- Item Pipeline:定义Item Pipeline来处理爬取到的数据存储。例如,将数据存储到MySQL数据库,可以使用
mysql - connector - python
库。
import mysql.connector
class MySQLPipeline:
def __init__(self, host, user, password, database):
self.host = host
self.user = user
self.password = password
self.database = database
@classmethod
def from_crawler(cls, crawler):
return cls(
host=crawler.settings.get('MYSQL_HOST'),
user=crawler.settings.get('MYSQL_USER'),
password=crawler.settings.get('MYSQL_PASSWORD'),
database=crawler.settings.get('MYSQL_DATABASE')
)
def open_spider(self, spider):
self.connection = mysql.connector.connect(
host=self.host,
user=self.user,
password=self.password,
database=self.database
)
self.cursor = self.connection.cursor()
def close_spider(self, spider):
self.cursor.close()
self.connection.close()
def process_item(self, item, spider):
insert_query = "INSERT INTO news (title, publish_time) VALUES (%s, %s)"
self.cursor.execute(insert_query, (item['title'], item['publish_time']))
self.connection.commit()
return item
- 配置Item Pipeline:在
settings.py
文件中启用定义好的Item Pipeline。
ITEM_PIPELINES = {
'news_crawler.pipelines.MySQLPipeline': 300,
}
2. Scrapy优化以提高爬取效率
- 并发设置:在
settings.py
中调整CONCURRENT_REQUESTS
参数,控制同时发送的请求数。例如,设置为CONCURRENT_REQUESTS = 32
,可以根据服务器性能和目标网站的承受能力适当调整。
- 下载延迟:通过设置
DOWNLOAD_DELAY
参数,给每个请求添加一定的下载延迟,避免对目标网站造成过大压力,同时也有助于避免被封IP。例如,DOWNLOAD_DELAY = 1
表示每个请求之间间隔1秒。
- 启用缓存:使用
scrapy - cache
插件,启用请求缓存,对于已经请求过的URL,直接从缓存中读取数据,减少重复请求。在settings.py
中配置HTTPCACHE_ENABLED = True
,并可以设置缓存过期时间等参数。
3. 应对反爬虫机制
- 随机User - Agent:使用
scrapy - fake - useragent
库,在每次请求时随机更换User - Agent,模拟不同的浏览器访问。在settings.py
中配置:
DOWNLOADER_MIDDLEWARES = {
'scrapy_fake_useragent.middleware.RandomUserAgentMiddleware': 400,
}
- IP代理:维护一个IP代理池,当检测到IP被封时,及时切换到其他可用的代理IP。可以使用
scrapy - proxy - middleware
库,并结合一些代理IP供应商提供的API来获取代理IP。在settings.py
中配置代理中间件:
DOWNLOADER_MIDDLEWARES = {
'scrapy_proxy_middleware.ProxyMiddleware': 543,
}
- 验证码处理:对于出现验证码的情况,可以使用第三方的验证码识别服务,如Tesseract(需要进行训练提高识别准确率)或一些商业的验证码识别API,在检测到验证码时,调用相应服务进行识别并填写。
- 模拟登录:如果部分网站需要登录才能访问新闻内容,可以使用
scrapy - selenium
库,结合Selenium和浏览器驱动(如ChromeDriver)模拟用户登录操作,获取登录后的Cookie,后续请求携带Cookie进行访问。