学习scrapy,总结下使用scrapy爬取豆瓣电影的demo,以及中间遇到的问题。
- 核心就是一个spider和一个item(爬取电影排名,名称,分数,评分人数,图片url)
class DouBanMovieItem(scrapy.Item):
rank = scrapy.Field()
movie_name = scrapy.Field()
score = scrapy.Field()
score_num = scrapy.Field()
pic_url = scrapy.Field()
class DoubanmovieSpider(scrapy.Spider):
name = 'doubanmovie'
allowed_domains = ['movie.douban.com/top250']
start_urls = ['https://movie.douban.com/top250/']
def parse(self, response):
item = DouBanMovieItem()
movies = response.css('ol.grid_view li')
for movie in movies:
item['pic_url'] = movie.css('div.pic a::attr(href)').extract()
item['rank'] = movie.css('div.pic em::text').extract()
item['movie_name'] = movie.css('div.info > div.hd > a > span:nth-child(1)::text').extract()
item['score'] = movie.css('div.info > div.bd > div.star > span.rating_num::text').extract()
item['score_num'] = movie.css('div.info > div.bd > div.star > span:nth-child(4)::text').extract()
yield item
next_page = response.css('div.paginator > span.next > a::attr(href)').extract_first()
if next_page is not None:
yield response.follow(next_page, callback=self.parse)
以上代码主要需要测试选择器定位的数据是否正确,对于豆瓣这类网站,肯定有反爬措施,所以一段时间以后上述的选择器可能无法定位到准确的数据,需要更改对应的代码。这通过scrapy shell 来进行调试更加方便。
在执行爬虫的时候,正常爬取了第一页数据,但是在爬取第二页数据的时候爬虫停止了,命令行有以下提示:
2018-09-11 20:56:33 [scrapy.spidermiddlewares.offsite] DEBUG: Filtered offsite request to 'movie.douban.com': <GET https://movie.douban.com/top250?start=25&filter=>
2018-09-11 20:56:33 [scrapy.core.engine] INFO: Closing spider (finished)
如上,第二页的urlhttps://movie.douban.com/top250?start=25&filter=可以通过浏览器正常打开,通过scrapy shell 也可以获取数据。而且程序也没有报错,感觉这里很奇怪,是不是应该抛个异常出来?最后查了下,这个问题是爬虫中定义的允许域allowed_domains=['movie.douban.com/top250']
与要爬取的url的域不一致。这里我有个猜测 是不是https://movie.douban.com/top250?start=25&filter=通过?带了参数,scrapy认为域是movie.douban.com
而不是movie.douban.com/top250
?于是将上面的allowed_domains修改成allowed_domains = ['movie.douban.com']
再执行爬虫就可以正常爬取了。或者在调用response.follow()
的时候增加一个关键字参数response.follow(next_page, callback=self.parse, dont_filter=True)
,经验证,这样做也是可以的