scrapy入门的一个例子
最近在尝试进行数据分析, 首先从数据挖掘开始, 无可避免地找到了scrapy.
安装以及最基础的教程
目标
- 爬取豆瓣动画tag下的所有标题图.
项目环境
- python 2.7
- windows
具体
首先打开豆瓣动画tag的页面, 分析一下urlhttps://movie.douban.com/tag/%E5%8A%A8%E7%94%BB?start=0&type=S
, start代表开始的顺序, 尝试改变数字大小, 页面正常跳转. 可以改变这个数字实现翻页.
再去页面里找我们需要的东西, 一张图片, 还有动画的信息. 用任意查看html源代码的工具, 很轻松可以找到以下标签.
<a class="nbg" href="https://movie.douban.com/subject/26419345/" title="探险活宝 第七季">
<img src="https://img3.doubanio.com/view/movie_poster_cover/ipst/public/p2248485714.jpg" alt="探险活宝 第七季" class="">
</a>
我们所需要的数据, 全部在这个img里面, 一个是 src 属性, 一个是 alt 属性. 明白了这些, 就可以开始敲代码了.
新建项目
配好环境后, 通过scrapy startproject xxxx
新建项目.
建立spider
spider需要放在spiders
文件夹下面, 新建一个.py文件, 里面用class声明一个蜘蛛.
import scrapy
class Spider(scrapy.Spider):
name = 'spider'
start_urls= [
]
def parse(self, response):
...
取得有效数据
结合我上面指出的标签, 可以通过css选择器获得我们的需要的数据.
img_arr = []
text_arr = []
for item in response.css('.nbg > img'):
img_arr.append(item.css('img::attr("src")').extract())
text_arr.append(item.css('img::attr("alt")').extract())
数据收集逻辑完毕.
将图片本地化
图片本地化使用了urllib2.
if not os.path.exists('temp/'):
os.mkdir('temp/')
for i in xrange(min(len(img_arr), len(text_arr))):
with open('temp/' + str(self.myenumerate) + '.' + text_arr[i][0] + img_arr[i][0][img_arr[i][0].rfind('.'):], 'wb+') as f:
req = urllib2.Request(img_arr[i][0], headers = self.head)
res = urllib2.urlopen(req)
f.write(res.read())
self.myenumerate +=1
f.close()
有几个地方需要注意下.
- 数据处理结束是个二维数组;
- 为了方便查看, 我增加了一个类内标识, self.myenumerate, 内容是数字
- 需要添加head, 否则会被豆瓣拦截.
完整代码
#-*- coding:utf-8 -*-
import scrapy
import urllib2
import os
class Spider(scrapy.Spider):
name = 'spider'
start_urls = [
'http://www.clannadbar.com/'
]
myenumerate = 0
head = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Charset': 'ISO-8859-1,utf-8;q=0.7,*;q=0.3', 'Accept-Encoding': 'none', 'Accept-Language': 'en-US,en;q=0.8', 'Connection': 'keep-alive'} //不设置header伪装浏览器, 会被豆瓣拒绝访问
def parse(self, response):
print("123000")
for i in xrange(1980 / 20):
url = 'https://movie.douban.com/tag/%E5%8A%A8%E7%94%BB?start=' + str(i * 20) + '&type=S'
yield scrapy.Request(url, callback = self.parse_deal, headers= self.head)
def parse_deal(self, response):
print("1230001")
img_arr = []
text_arr = []
for item in response.css('.nbg > img'):
img_arr.append(item.css('img::attr("src")').extract())
text_arr.append(item.css('img::attr("alt")').extract())
if not os.path.exists('temp/'):
os.mkdir('temp/')
for i in xrange(min(len(img_arr), len(text_arr))):
with open('temp/' + str(self.myenumerate) + '.' + text_arr[i][0] + img_arr[i][0][img_arr[i][0].rfind('.'):], 'wb+') as f:
req = urllib2.Request(img_arr[i][0], headers = self.head)
res = urllib2.urlopen(req)
f.write(res.read())
self.myenumerate +=1
f.close()
运行
回到项目根目录, 通过scrapy crawl 爬虫名称
, 运行爬虫.
问题总结
- 最好的方式, 是在scrapy的配置中设定header, 可暂时没找到方法, 才在代码中手动设置
- 数据拉取下来变成了二维数组, 还需要再看下数据结构
- 虽然说的是所有, 实际上是自己手动找了1980这个最大值, 通过挖掘获得会更好
- 爬虫爬的跟链接其实是没用的, 只是为了启动爬虫. 这么做的原因, 是我没想好怎么在parse之前, 用循环生成链接, 只好嵌套一层.
お終い。