使用scrapy框架进行下列爬虫任务
实验任务
(一)显示影片基本信息
访问豆瓣电影Top250(https://movie.douban.com/top250?start=0),获取每部电影的中文片名、排名、评分及其对应的链接,按照“排名-中文片名-评分-链接”的格式显示在屏幕上。
(二)存储影片详细信息
访问豆瓣电影Top250(https://movie.douban.com/top250?start=0),在问题1的基础上,获取每部电影的导演、编剧、主演、类型、上映时间、片长、评分人数以及剧情简介等信息,并将获取到的所有信息(一和二中得到的信息)保存至本地文件中。
此外,创建MySQL数据库movies,在该数据库中创建表格topMovies, 保存至本地文件的同时,将所有信息保存至表格topMovies中。
接下来按我的步骤:
1.新建工程 在PyCharm中新建一个名称为“scrapyProject”的工程。在“scrapyProject”工程底部打开Terminal窗口(如图3-8所示),在命令提示符后面输入命令“pip install scrapy”,下载Scrapy框架所需文件
2.继续输入命令“scrapy startproject movieScrapy”,创建Scrapy爬虫框架相关目录和文件。创建完成以后的具体目录结构如图3-9所示,这些目录和文件都是由Scrapy框架自动创建的,不需要手动创建。
在Scrapy爬虫程序目录结构中,各个目录和文件的作用如下: l Spiders目录:该目录下包含爬虫文件,需编码实现爬虫过程; l __init__.py:为Python模块初始化目录,可以什么都不写,但是必须要有; l items.py:模型文件,存放了需要爬取的字段; l middlewares.py:中间件(爬虫中间件、下载中间件),本案例中不用此文件; l pipelines.py:管道文件,用于配置数据持久化,例如写入数据库; l settings.py:爬虫配置文件; scrapy.cfg:项目基础设置文件,设置爬虫启用功能等。在本案例中不用此文件。
3.items.py的具体代码内容如下:
import scrapy
class MoviescrapyItem(scrapy.Item):
# define the fields for your item here like:
# 排名
rank = scrapy.Field()
# 中文片名
title = scrapy.Field()
# 评分
rating = scrapy.Field()
# 链接
link = scrapy.Field()
# 导演
director = scrapy.Field()
# 编剧
writer = scrapy.Field()
# 主演
starring = scrapy.Field()
# 类型
genre = scrapy.Field()
# 上映时间
release_date = scrapy.Field()
# 片长
duration = scrapy.Field()
# 评分人数
rating_count = scrapy.Field()
# 剧情简介
description = scrapy.Field()
4.在Terminal窗口输入命令“cd movieScrapy”,进入对应的爬虫工程中,再输入命令“scrapy genspider movieSpider movie.douban.com”,这时,在spiders目录下会出现一个新的Python文件movieSpider.py,该文件就是我们要编写爬虫程序的位置。下面是poemSpider.py的具体代码:
import scrapy
from scrapy import Request
from ..items import MoviescrapyItem
class MovieSpider(scrapy.Spider):
name = 'movieSpider'
allowed_domains = ['movie.douban.com']
start_urls = ['https://movie.douban.com/top250?start=0']
def parse(self, response):
# 提取每部电影信息
movies = response.xpath('//div[@class="item"]')
for movie in movies:
item = MoviescrapyItem()
item['rank'] = movie.xpath('div[@class="pic"]/em/text()').get()
item['title'] = movie.xpath('div[@class="info"]/div[@class="hd"]/a/span[@class="title"]/text()').get()
item['rating'] = movie.xpath('div[@class="info"]/div[@class="bd"]/div[@class="star"]/span[@class="rating_num"]/text()').get()
item['link'] = movie.xpath('div[@class="info"]/div[@class="hd"]/a/@href').get()
# 打印电影信息到屏幕上
print(f"{item['rank']}-{item['title']}-{item['rating']}-{item['link']}")
# 请求电影详情页并传递item
yield Request(item['link'], callback=self.parse_detail, meta={'item': item})
# 处理下一页
next_page = response.xpath('//span[@class="next"]/a/@href').get()
if next_page:
yield Request(response.urljoin(next_page))
def parse_detail(self, response):
# 获取电影的详细信息
item = response.meta['item']
# 提取电影的详细信息
info = response.xpath('//div[@id="info"]')
# 导演
director = response.xpath('.//span[contains(text(), "导演")]/following-sibling::span[1]/a/text()').getall()
item['director'] = ','.join(director) if director else None
# 编剧
writer = response.xpath('.//span[contains(text(), "编剧")]/following-sibling::span[1]/a/text()').getall()
item['writer'] = ','.join(writer) if writer else None
# 主演
actor = response.xpath('.//span[contains(text(), "主演")]/following-sibling::span[1]/a/text()').getall()
item['starring'] = ','.join(actor[:10]) if actor else None # 只保留前10个主演
# 类型
genre = response.xpath('.//span[contains(text(), "类型")]/following-sibling::span[1]/text()').get()
item['genre'] = genre.strip() if genre else None
# 上映时间
release_date = response.xpath('.//span[contains(text(), "上映日期")]/following-sibling::span[1]/text()').get()
item['release_date'] = release_date.strip() if release_date else None
# 片长
duration = response.xpath('.//span[contains(text(), "片长")]/following-sibling::span[1]/text()').get()
item['duration'] = duration.strip() if duration else None
# 评分人数
rating_count = response.xpath('//span[@property="v:votes"]/text()').get()
item['rating_count'] = rating_count.strip() if rating_count else None
# 剧情简介
description = response.xpath('//span[@property="v:summary"]/text()').get()
item['description'] = description.strip() if description else None
# 将item传递给Pipeline处理
yield item
5.编写代码文件settings.py
BOT_NAME = 'movieScrapy'
SPIDER_MODULES = ['movieScrapy.spiders']
NEWSPIDER_MODULE = 'movieScrapy.spiders'
REQUEST_FINGERPRINTER_IMPLEMENTATION = '2.7'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4421.5 Safari/537.36'
# Obey robots.txt rules
ROBOTSTXT_OBEY = False
# 设置日志打印的等级
LOG_LEVEL = 'WARNING'
ITEM_PIPELINES = {
'movieScrapy.pipelines.MoviescrapyPipeline': 1,
}
6.编写完成以后的pipelines.py代码如下(为了让你连接数据库):
from itemadapter import ItemAdapter
import json
import pymysql
class MoviescrapyPipeline:
def __init__(self):
# 连接MySQL数据库
self.connect = pymysql.connect(
host='localhost',
port=3306,
user='root',
passwd='123456', # 设置成用户自己的数据库密码
db='movies',
charset='utf8'
)
self.cursor = self.connect.cursor()
def process_item(self, item, spider):
# 写入数据库
sql = '''INSERT INTO topMovies (movie_rank, title, rating, link, director, writer, starring, genre, release_date, duration, rating_count, description)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)'''
self.cursor.execute(sql, (
item['rank'], item['title'], item['rating'], item['link'], item['director'],
item['writer'], item['starring'], item['genre'], item['release_date'], item['duration'],
item['rating_count'], item['description']
))
self.connect.commit()
return item
def close_spider(self, spider):
# 关闭数据库连接
self.cursor.close()
self.connect.close()
7.为了把爬取到的数据保存到MySQL数据库中,需要首先安装PyMySQL模块。 在PyCharm开发界面中点击“File->Settings…”,在打开的设置界面中,先点击“Project scrapyProject”,再点击“Python Interpreter”,会弹出的设置界面,点击界面底部的“+”。
8.在弹出的模块安装界面中,先在搜索框中输入“pymysql”,然后,在搜索到的结果中点击“PyMySQL”条目,最后,点击界面底部的“Install Package”,开始安装模块,如果安装成功,会出现的信息。
9.最后有两种执行Scrapy爬虫的方法,第一种是在Terminal窗口中输入命令“scrapy crawl movieSpider”,然后回车运行,等待几秒钟后即可完成数据的爬取。第二种是在poemScrapy目录下新建Python文件run.py(run.py应与scrapy.cfg文件在同一层目录下),并输入下面代码:
from scrapy import cmdline
cmdline.execute("scrapy crawl poemSpider".split())
在run.py代码区域点击鼠标右键,在弹出的菜单里选择“Run”运行代码,就可以执行Scrapy爬虫程序。执行成功以后,就可以看到生成的数据文件data.txt
这是mysql里的数据(注意mysql这个表得自己创,这个我没给出代码,可以参考我的表结构)