Scrapy用于爬取动漫数据②
在这篇文章中我们可以了解到什么?
・使用Scrapy创建基本爬虫的方法
・Scrapy和MongoDB的连接方式
这是一篇关于什么的文章?
我会介绍一下爬虫(Spider)。
这是上一篇文章的续篇。在上一篇文章中,我们学会了使用xpath进行网页抓取。而这次,我们将使爬虫能够自动抓取多个网页。
代码已经上传到GitHub上了。
蜘蛛的概述
def parse(self, response):
if self.num == self.limit_id:
pass
else:
url = 'http://anikore.jp/anime/' + str(self.num) + '/'
anime_id = self.num
title = response.xpath('//*[@id="clm24"]//h2/a[@class="blk_lnk"]/text()').extract_first()
point = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[1]/span[2]/text()').extract()
point_story = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[2]/span[2]/text()').extract()
point_animation = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[3]/span[2]/text()').extract()
point_vc = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[4]/span[2]/text()').extract()
point_music = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[5]/span[2]/text()').extract()
point_chara = response.xpath('//*[@id="main"]/div[2]/div[2]/div[1]/div[6]/span[2]/text()').extract()
total_point = response.xpath('//*[@id="main"]/div[2]/div[2]/div[2]/div[1]/span[2]/text()').extract()
review_num = response.xpath('//*[@id="main"]/div[2]/div[2]/div[2]/div[2]/span[2]/text()').extract()
fav_num = response.xpath('//*[@id="main"]/div[2]/div[2]/div[2]/div[3]/span[2]/text()').extract()
ranking = response.xpath('//*[@id="main"]/div[2]/div[2]/div[2]/div[4]/span[2]/text()').extract()
summary = response.xpath('//*[@id="main"]/div[2]/div[3]/blockquote/text()').extract()
print("____________________________________________________")
print(self.num)
self.num += 1
# if anime page exist
if title is not None:
#output
yield {"anime_id":anime_id,"title":title,"point":point,"point_story":point_story,"point_animation":point_animation, \
"point_vc":point_vc,"point_music":point_music,"point_chara":point_chara, \
"total_point":total_point, "review_num":review_num, "fav_num":fav_num, \
"ranking":ranking, "summary":summary}
# crawl next anime page
next_url = 'http://anikore.jp/anime/' + str(self.num) + '/'
yield Request(next_url, callback=self.parse, dont_filter=True)
# If animepage does not exist, redirect to homepage. So, title is None.
else:
#crawl next anime page
next_url = 'http://anikore.jp/anime/' + str(self.num) + '/'
yield Request(next_url, callback=self.parse, dont_filter=True)
代码要点
1. 这次的URL规则是https://www.anikore.jp/anime/[动漫ID]/,所以通过递增动漫ID来访问所有动漫页面。
2. 使用response.xpath()进行各种爬虫操作。
3. 通过yield {“anime_id”:动漫ID,”title”:标题,…,}来输出爬取的数据。
4. 通过yield Request(next_url, callback=self.parse, dont_filter=True)跳转到下一个动漫页面。
与MongoDB的连接
Scrapy有一个叫做pipeline的结构。关于Scrapy的结构,我非常想参考@checkpoint先生的这篇文章,因为它非常易懂。
下面是pipeline.py的代码。
from pymongo import MongoClient # mongoDB との接続
import datetime
from scrapy.conf import settings
class MongoDBPipeline(object):
def __init__(self):
# インスタンス生成時に渡された引数で、変数初期化
connection = MongoClient(
settings['MONGODB_SERVER'],
settings['MONGODB_PORT'])
db = connection[settings['MONGODB_DB']]
self.collection = db[settings['MONGODB_COLLECTION']]
def process_item(self, item, spider):
self.collection.insert(dict(item))
return item
有四个名为MONGODB_*的变量,这些变量在setting.py文件中被定义。
#mongoDB settings
MONGODB_SERVER = 'localhost'
MONGODB_PORT = 27017
#db name
MONGODB_DB = 'anikore'
#collection name
MONGODB_COLLECTION = "users"
在这种情况下,会在名为anikore的数据库中创建一个名为user的集合,并将数据存入其中。
执行结果
请用下面的命令运行蜘蛛。
scrapy crawl anime
也可以同时将数据写入CSV文件中。
scrapy crawl anime -o anime.csv
然后,你应该能在终端中感受到蜘蛛的移动。
接着,如果MongoDB数据已经保存下来,那就是成功了。太好了。
此外
如果我们运用本次介绍的爬虫技巧,似乎可以收集任意网站的数据。然而,这并非如此简单的现实情况。例如,用户的数据只有在登录后才能查看。也就是说,作为爬虫的功能,我们需要在登录页面进行登录。这可以通过Scrapy的FormRequest功能来实现。
感谢您的阅读。