1 问题描述
通过Scrapy,实现CSDN热门博客抓取,并以博客大标题对本地HTML的命名
2 解题提示
- 创建Scrapy项目: Scrapy startproject 【项目名称】
- 创建Spider文件: Scrapy genspider 【爬虫文件名】 “【allowed_domain】”
- 开启项目文件: Scrapy crawl 【爬虫文件名】
- yield Request 向调度器发送一个请求,yield dict 向管道文件发送一个数据
- Request中的callback为得到响应后的回调函数
3 评分标准
- 完成Scrapy项目的搭建 10分
- 实现热门博客抓取与本地保存 10分
- 代码注释,规范10分
4 要点解析
- scrapy 原理介绍
- 各组件功能介绍
5 实现步骤
- 创建scrapy框架
- 创建spider文件
- 编辑爬虫文件
# -*- coding: utf-8 -*-
import scrapy
import urllib.request as ur
import urllib.parse as up
class BlogspiderSpider(scrapy.Spider):
# name同spider的名字一致
name = 'blog_spider'
# 可以过滤不是本web的request
allowed_domains = ['blog.csdn.net']
keyword = 'python进阶'
# 定义start_request可以封装headers,以及代理IP
# start_urls = ['http://blog.csdn.net/']
def start_requests(self):
# 热门blog的网页解析,其中中文需要转译:还是采用用户端输入的形式,不定页面以及关键词了
# pn_start = int(input("起始页:"))
# pn_end = int(input("结束页:")) # 实际爬虫获取最大页面
# keyword = input("关键词:")
# 循环页面
pn_start = 1
pn_end = 10
for pn in range(pn_start, pn_end + 1):
url_data = {
'p': pn,
'q': self.keyword
}
# 编码关键词
url_data = up.urlencode(url_data)
# 构建url
url = 'https://so.csdn.net/so/search/s.do?%s&t=blog&viparticle=&domain=&o=&s=&u=&l=&f=&rbg=0' % url_data
yield scrapy.Request(
url=url,
callback=self.parse,
)
# 将start_request产生的response传递给parse,并进行处理
def parse(self, response):
# 这个response是bytes类型,可以直接xpath找到热门文章
# href_s是一个列表,并且xpath是scrapy的形式,使用extract()
href_s = response.xpath('//div[@class="limit_width"]/a[1]/@href').extract()
# 处理每一个href对应的热门博客,并且返回start_request
for href in href_s:
yield scrapy.Request(
url=href,
callback=self.parse2,
)
def parse2(self, response):
# 不取索引0,使用extract_first
title = response.xpath('//div[@class="article-title-box"]/h1/text()').extract_first()
# html 文件,body等同于ur.urlopen().read()
data = response.body
# 封装item,并且传递给pipeline
item = dict(
title=title,
data=data,
)
# scheduler 引擎会自动判断
yield item
- 存储数据
class Homework1Pipeline(object):
def process_item(self, item, spider):
# 获取item的title,data值
# 将html存储当csdn_blog文件夹里
with open('csdn_blog/%s.html' % item['title'], 'wb') as f:
f.write(item['data'])
return item
- 开启项目文件