爬虫之scrapy(二)
爬虫之scrapy(二)
在运行scrapy之前,需要了解的先行知识戳这里
本文不讲解scrapy框架的工作原理,以及相关的理论知识。我们以实用为目的,保证看完就能用。那么,我们开始吧。
创建项目
cd到指定的路径下,使用以下命令创建项目
scrapy startproject mySpider
创建之后会生成以下项目文件。
主要文件介绍:
-
scrapy.cfg :项目的配置文件
-
mySpider/ :项目的Python模块,将会从这里引用代码
-
mySpider/items.py :项目的目标文件
-
mySpider/pipelines.py :项目的管道文件
-
mySpider/settings.py :项目的设置文件
-
mySpider/spiders/ :存储爬虫代码目录
明确爬取内容
在正式写爬虫之前,得做一些准备工作。
- 明确需要爬取什么数据
- 分析目标页面html代码,获取写对应数据的xpath
我们以获取豆瓣TOP250(http://movie.douban.com/top250)
电影名字、信息、评分为例:
分析页面,写对应的xpath,然后用chroPath检测是否正确。具体分析过程暂且不写。最终结果如下:
item_list = response.xpath('//ol[@class="grid_view"]/li/div[@class="item"]')
title = './/div[@class="hd"]/a/span[1]/text()'
#信息
infomation = './/div[@class="bd"]/p/text()'
#评分
score = './/div[@class="star"]/span[@class="rating_num"]/text()'
#简介
introduction = './/p[@class="quote"]/span/text()'
编写爬虫
准备工作到此已经全部完成,接下来,就开始干正事!!
1)首先,告诉Scrapy,我要抓哪些数据
打开 items.py直接在系统生成的类里申明相应的变量,存储对应的数据。
import scrapy
# 因为创建的项目名叫 movie,所以生成系统生成了MoviewItem
# 貌似。。。Movie 打错了。。。
class MoviewItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
#标题
title = scrapy.Field()
#信息
infomation = scrapy.Field()
#评分
score = scrapy.Field()
#简介
introduction = scrapy.Field()
接下来,就是写和网页相关的爬虫代码了。那么问题来了,应该写在哪呢?纵观生成的文件,没有适合写的文件啊
此时,我想到了,伟大领袖毛爷爷的一句话:“没有条件,就创造条件”。简单粗暴,干就完事了。
2)创建爬虫文件
scrapy genspider douban "douban.com"
看看这个命令,没错,一个字,干!(gen)。注意,是gen(已经打错好几次命令了。。。)
“douban.com”,是告诉scrapy不要放荡不羁爱*,只在这个域名下爬,别上错床
运行完之后,便会在spiders文件夹下生成douban.py文件
不要犹豫,打开它!!!
import scrapy
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['douban.com']
start_urls = ['http://douban.com/']
def parse(self, response):
pass
生成的参数:
name: 爬虫的名,运行的时候用
allowed_domains: 允许爬虫爬的域名,就是给你的小虫子关到笼子里去。
start_urls:起始地址
parse:用来处理爬取到的页面数据
位置有了,那就直接开搞!
- 修改起始地址
- 从items文件导入MoviewItem类
- 因为每一页只有25个,观察发现,通过get方式传入start参数实现翻页。所以,对URL进行处理。
- 在parse中写xpath。
一顿操作之后,结果如下:
# -*- coding: utf-8 -*-
import scrapy
from moview.items import MoviewItem
class DoubanSpider(scrapy.Spider):
name = 'douban'
allowed_domains = ['movie.douban.com']
url = 'http://movie.douban.com/top250?start='
index = 0
start_urls = ['http://movie.douban.com/top250?start=' + str(index)]
def parse(self, response):
item = MoviewItem()
item_list = response.xpath('//ol[@class="grid_view"]')
for each in item_list:
item['title'] = each.xpath('.//div[@class="hd"]/a/span[1]/text()').extract()[0]
#信息
item['infomation'] = each.xpath('.//div[@class="bd"]/p/text()').extract()[0]
#评分
item['score'] = each.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()').extract()[0]
#简介
item['introduction'] = each.xpath('.//p[@class="quote"]/span/text()').extract()[0]
yield item
# pass
# 将下一页的URL加入请求队列。
if self.index < 225:
self.index += 25
yield scrapy.Request(self.url + str(self.index),callback=self.parse)
发现没?items类,就当他是个Map字典类型,在items类写的变量当作键值就OK。
对了,因为要处理的不仅仅只有一个页面,还要爬翻页后的页面。因此,增加了后边三行代码。大概意思就是,把下一页的URL扔到请求队列,让scrapy有空的时候把这个页面的数据页拉回来。
其实,写到这,爬虫已经可以用了。只是,把上边的yield item改成保存数据的代码就OK了。大概这个样子
def parse(self, response):
if not os.path.exists('./qcmn'):
os.makedirs('./qcmn')
else:
url = response.xpath("//div[@id='big-pic']//p//a//img/@src").extract()[0]
file_name = url.split("/")
with urllib.request.urlopen(url, timeout=30) as response, open('./qcmn/' + file_name[-2] + file_name[-1], 'wb') as f_save:
f_save.write(response.read())
f_save.flush()
f_save.close()
print(file_name[-2] + file_name[-1] + " 保存成功")
但是,这样总觉得不够完整。来来来,继续搞。
当parse使用yield item 之后,这些数据会去哪呢?这个时候,scarpy会把这些数据扔到另一个队列中,由管道文件(pipelines)处理。
但是,注意,在使用管道文件之前,需要打开setting文件,将管道文件放出来。
ITEM_PIPELINES = {
'moview.pipelines.MoviewPipeline': 300,
}
后边的数字表示优先级,暂时不用管它。总之,在settings.py文件中找到ITEM_PIPELINES,然后去掉注释就OK。
接着,打开piplines文件
import pymysql
class MoviewPipeline(object):
def __init__(self):
self.connect = pymysql.connect(host='127.0.0.1',user='root',password='root',db='spider')
self.cursor = self.connect.cursor()
def process_item(self, item, spider):
sql = """
INSERT into movie (title,infomation,score,introduction) VALUES(%s,%s,%s,%s)
"""
self.cursor.execute(sql,(item['title'],item['infomation'],item['score'],item['introduction']))
return item
def close_spider(self,spider):
self.cursor.close()
self.connect.close()
这里我是把数据写到数据库了,你也可以根据自己需要,写到本地文件。
最后的最后,为了防止服务器发现有人在悄咪咪的干这些见不得人的事,我们要设置一点点东西。
打开settings.py文件。
# 注释掉接受语言为英语的这一行,
# 添加user-agent 骗骗服务器
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
# 'Accept-Language': 'en',
'User-Agent' : 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36'
}
# 注释掉 robots.txt (就是不遵守网站的允许的爬虫约定)
# Obey robots.txt rules
# ROBOTSTXT_OBEY = True
OK,大功告成,运行
scrapy craw douban
让这个小虫子愉快的跑起来吧。。。
注意!!命令中的名字,不是项目名,是name变量的值噢!!
总结
上述过程是沿着scrapy框架爬取过程的流程写的,写代码的时候不必要按照这个流程写。但是以下这几个步骤不能少
- 创建项目和新建爬虫文件
- 确定目标网站以及明确需要的数据(items)
- 分析目标网站,整理正确的xpath,用于从网页中提取需要的信息。(parse)
- 在管道文件中写数据处理。
- 根据需要,改写settings
上一篇: JS检测移动端横竖屏的代码
下一篇: 字符串与ASCII的转换