1、项目简介
本次项目利用scrapy爬虫框架实现抓取豆瓣top250的详情页信息,主要字段如下:
主要字段:
Num——》电影排名
DetailLink——》详情页链接
Title——》电影标题
RatingNum——》评分
Votes——》评价人数
Director——》导演
Writer——》编剧
Actor——》主演
Type——》类型
ReleaseDate——》上映时间
RunTime——》片长
2、创建项目文件
创建一个scrapy工程
crapy startproject douban
创建爬虫源文件
scrapy genspider douban250 www.douban.com
3、爬虫文件配置
3.1配置setting文件
1)反爬配置
# 关闭 robots
ROBOTSTXT_OBEY = False
# 配置请求头
```python
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36'
# 为方便调试 修改日志等级为‘ERROR’
LOG_LEVEL = 'ERROR'
2)开启管道
ITEM_PIPELINES = {
'douban.pipelines.DoubanPipeline': 300,
}
3.2配置items文件
定义要爬取的字段
class DoubanItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
Num = scrapy.Field()
DetailLink = scrapy.Field()
Title = scrapy.Field()
RatingNum = scrapy.Field()
Votes = scrapy.Field()
Director = scrapy.Field()
Writer = scrapy.Field()
Actor = scrapy.Field()
Type = scrapy.Field()
ReleaseDate = scrapy.Field()
RunTime = scrapy.Field()
4、爬虫文件编写
4.1、字段空值处理
在爬取字段过程中,有些电影详情页没有相应的字段信息,当程序运行到此处时便会报错,影响爬虫的运行,其次为了储存信息结构的 完成性,该字段自该条记录应该给空值占位。为了处理上述问题,可以编写一个处理字段空值的函数如下:
def try_except(self, response, xpath_str):
try:
field = response.xpath(xpath_str).extract_first()
except:
field = ''
return field
4.2、目录页解析函数编写
def parse(self, response):
li_list = response.xpath('//*[@id="content"]/div/div[1]/ol/li')
for li in li_list:
item = DoubanItem()
# 解析每个字段时调用4.1定义的空值处理函数,传入网页相应和xpath表达式
item['Num'] = self.try_except(li, './/em/text()')
item['DetailLink'] = self.try_except(li, './/a[1]/@href')
# 提交详情页链接,经过调度,执行生成scrapy.http.Response 对象并送回给详情页解析方法
yield scrapy.Request(item['DetailLink'],
callback=self.parse_detail_html,
meta={'item': deepcopy(item)})
4.2、翻页代码编写
抓取下一页的链接并补全链接,将下一页的response对象给到目录页解析方法
next_url = 'https://movie.douban.com/top250' + self.try_except(response, '//*[@id="content"]/div/div[1]/div[2]/span[3]/a/@href')
print(f'已完成:{self.i}页')
self.i += 1
if self.i <= 10:
yield scrapy.Request(next_url,
callback=self.parse)
4.3、详情页解析函数编写
解析过程中,避免出现空值,每个字段都调用空值处理函数进行解析。
def parse_detail_html(self, response):
item = response.meta['item']
item['Title'] = self.try_except(response, '//*[@id="content"]/h1/span[1]/text()')
item['RatingNum'] = item['Title'] = self.try_except(response, '//*[@id="interest_sectl"]/div[1]/div[2]/strong/text()')
item['Votes'] = self.try_except(response, '//*[@id="interest_sectl"]/div[1]/div[2]/div/div[2]/a/span/text()')
item['Director'] = self.try_except(response, '//*[@id="info"]/span[1]/span[2]/a//text()')
item['Writer'] = self.try_except(response, '//*[@id="info"]/span[2]/span[2]//text()')
item['Actor'] = self.try_except(response, '//*[@id="info"]/span[3]/span[2]//text()').replace('\n', '')
item['Type'] = self.try_except(response, '//*[@id="info"]/span[@property="v:genre"]//text()')
item['ReleaseDate'] = self.try_except(response, '//*[@id="info"]/span[10]/text()')
item['RunTime'] = self.try_except(response, '//*[@id="info"]/span[13]/text()')
yield item
5、编写pipeline文件,进行持久化存储
class DoubanPipeline:
def open_spider(self,spider):
self.f = open('doubantop250.csv', 'w', encoding='utf-8')
def process_item(self, item, spider):
content = str(dict(item)) + ',\n'
self.f.write(content)
return item
def close_spider(self,spider):
self.f.close()
# 6、执行程序,信息查看
执行命令
scrapy crawl douban
程序运行提示
部分信息预览