相关工具
- Python 3.6.1
- Scrapy 1.4.0
- PyCharm (亲测VS Code无法运行、调试scrapy代码)
创建一个scrapy项目
在你的工作目录的文件夹下打开命令提示符窗口,输入:
scrapy startproject demo
如果出现下面的提示,则说明创建成功:
image.png使用PyCharm打开这个scrapy项目,它的目录结构是这样的:
image.png- scrapy.cfg ——主要包含的是项目的相关设置。
- demo ——是用于编写爬虫的目录。
- items.py ——定义我们所要爬取的信息的相关属性。
- middlewares.py ——爬虫中间件,这里可以用过自定义相关的方法,用来处理爬虫的响应和请求。
- pipelines.py ——当数据被爬虫爬取下来后,它会被发送到item pipelines中,每个item pipelines组件(有时称为“项目管道”)是一个实现简单方法的Python类。他们收到一个项目并对其执行操作,还决定该项目是否应该继续通过管道或被丢弃并且不再被处理。
- settings.py ——项目的设置文件。
编写代码
在spiders文件夹下创建douban_spider.py文件:
image.png这是一个空的.py文件,然后在这编写爬虫代码:
# 爬虫类需要继承scrapy下的Spider类。
import scrapy
class douban_movie_spider(scrapy.Spider):
# 项目的启动名
name = "douban_movie"
# 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
headler = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
'Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
}
# 开始链接
start_urls = [
'https://movie.douban.com/top250'
]
# start_requests方法为scrapy的方法,我们对它进行重写。
def start_requests(self):
# 将start_url中的链接通过for循环进行遍历。
for url in self.start_urls:
# 通过yield发送Request请求。
# 这里的Reques注意是scrapy下的Request类。注意不要导错类了。
# 这里的有3个参数:
# 1、url为遍历后的链接
# 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
# 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。
yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)
# 重写parse对start_request()请求到的数据进行处理
def parse(self, response):
pass
页面分析
chrome浏览器打开https://movie.douban.com/top250,点击f12开发者工具,使用选取工具选取整个电影的信息,可以发现,所有的信息都是放在单独的一个li标签中的,而且在li下还有一个class为item的div包裹着所有的信息:
image.pngparse方法
def parse(self, response):
# 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item
for quote in response.css('div.item'):
# 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下
yield {
"电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
"评分":quote.css('div.info div.bd div.star span.rating_num::text').extract(),
"引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
}
写完上面的代码,其实只是抓取一页的罢了,为了抓取完整的top250榜单,我们需要让爬虫跳转到下一页再进行循环抓取,因为每个页面的结构是一样的,所以不用担心会抓取不到。
image.pngnext_url=response.css('div.paginator span.next a::attr(href)').extract()
然后,需要对next_url进行判断是否存在,然后再次发送Request请求。这样爬虫就会在爬完一个页面后点击下一页再继续爬去,往复循环,直到爬取完毕。
if next_url:
next_url="https://movie.douban.com/top250"+next_url[0]
print(next_url)
yield scrapy.Request(next_url,headers=self.headler)
那么到这里,代码就写完了。
然后我们来运行一下这个爬虫,scrapy框架是通过命令来启动爬虫的,
在项目根目录下打开命令提示符,输入:
scrapy crawl douban_movie -o douban_movice.csv -t csv
保存信息的最简单的方法是通过Feed exports,主要有四种:JSON,JSON lines,CSV,XML。
为了方便直接查看内容,我们将结果用csv导出。
-o 后面是导出文件名,-t 后面是导出类型。
爬虫运行后,就会输出大量的日志信息和爬取的网页内容,且scrapy会把爬取到的结果保存到douban_movice.csv这个文件里:
image.png image.png image.png
但是,有个问题,如果爬虫报错了怎么办?
因为是用命令启动的爬虫,所以爬虫的日志信息都是显示在cmd中的,这样日志信息阅读起来非常的不友好。且Scrapy默认是不能在IDE中调试的,我们可以在根目录中新建一个run.py文件,在里面写入以下内容:
image.pngfrom scrapy import cmdline
name='douban_movie -o douban.csv -t csv'
cmd = 'scrapy crawl {0}'.format(name)
cmdline.execute(cmd.split())
运行这个文件后,所有的日志信息日志信息就会输出在IDE(PyCharm)下了,便于调试:
image.png在PyCharm中查看爬取结果:
image.png完整代码
# 爬虫类需要继承scrapy下的Spider类。
import scrapy
class douban_movie_spider(scrapy.Spider):
# 项目的启动名
name = "douban_movie"
# 如果网站设置有防爬措施,需要添加上请求头信息,不然会爬取不到任何数据
headler = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 '
'Safari/537.36',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8'
}
# 开始链接
start_urls = ['https://movie.douban.com/top250']
# start_requests方法为scrapy的方法,我们对它进行重写。
def start_requests(self):
# 将start_url中的链接通过for循环进行遍历。
for url in self.start_urls:
# 通过yield发送Request请求。
# 这里的Reques注意是scrapy下的Request类。注意不到导错类了。
# 这里的有3个参数:
# 1、url为遍历后的链接
# 2、callback为发送完请求后通过什么方法进行处理,这里通过parse方法进行处理。
# 3、如果网站设置了防爬措施,需要加上headers伪装浏览器发送请求。
yield scrapy.Request(url=url, callback=self.parse, headers=self.headler)
# 重写parse对start_request()请求到的数据进行处理
def parse(self, response):
# 这里使用scrapy的css选择器,既然数据在class为item的div下,那么把选取范围定位div.item
for quote in response.css('div.item'):
# 通过yield对网页数据进行循环抓取,我们要抓取的内容有3个,分别如下
yield {
"电影名": quote.css('div.info div.hd a span.title::text').extract_first(),
"评分": quote.css('div.info div.bd div.star span.rating_num::text').extract(),
"引言": quote.css('div.info div.bd p.quote span.inq::text').extract()
}
next_url = response.css('div.paginator span.next a::attr(href)').extract()
if next_url:
next_url = "https://movie.douban.com/top250"+next_url[0]
print(next_url)
yield scrapy.Request(next_url, headers=self.headler)
# 翻页
next_page = response.xpath('//span[@class="next"]/a/@href')
if next_page:
url = response.urljoin(next_page[0].extract())
yield scrapy.Request(url, self.parse)
网友评论