昨天,我发布了爬取游戏发售表的文章,有一个小伙伴看完了以后,非常的困扰,他问我说,“仙草哥哥,你这个爬虫程序虽然很好,基本的功能也实现了,但是我觉得它太简单了,总共才几十行,不像一个真正的程序。如果我拿去给朋友展示的话,这样的程序感觉都很没有面子,这可如何是好呢?”
我说,“程序最重要的是功能,你不要老是在意代码的行数,我们用几十行就完成了爬虫任务,这不好吗?”
他说,“可是,这样的代码还是太简单了,你能不能教教我,怎么才能把爬虫代码写的多一点,像一个真正的程序一样呢?比如说,如果期末我要交一份爬虫课的作业,应该怎样才能得到比较高的评价呢?”
好吧,其实这也没什么困难的,只要能够保留原本的功能,再加上额外的数据保存,就能解决问题了。比如说,将之前的程序升级一下,采用scrapy框架爬取数据,并将结果保存到mongo数据库中,这样就能比之前的requests程序更加丰富了
实现分析 settings.py需要修改几个重要的配置信息,主要包括爬虫协议的遵守,user-agent的定义
# 修改默认的user-agent USER_AGENT = "Mozilla/5.0" # 不遵守爬虫协议 ROBOTSTXT_OBEY = Falseitems.py
在字段定义部分,要包含所有我们所需的数据,对于爬取游戏发售表来说,我们需要包含游戏名,出版时间,类型,信息等
import scrapy
class GameItem(scrapy.Item):
name = scrapy.Field() # 游戏名
publish_time = scrapy.Field() # 出版时间
type = scrapy.Field() # 类型
producer = scrapy.Field() # 制作商
info = scrapy.Field() # 信息
collection = scrapy.Field() # mongo中保存的位置
spider.py
在爬虫部分,要实现两个功能,请求的发送和响应的处理,首先通过起始url,获得响应,然后得到更多的url,继续处理响应
def parse(self, response):
# 从响应中提取数据
game = response.xpath("//li[@class='lx1']")
# 定义保存的信息
item = GameItem()
for i in game:
item["name"] = i.xpath(".//div[@class='tit']/a/text()").extract_first()
item["publish_time"] = i.xpath(".//div[@class='txt'][1]/text()").extract_first()
item["type"] = i.xpath(".//div[@class='txt'][2]/a/text()").extract_first()
item["producer"] = i.xpath(".//div[@class='txt'][3]/text()").extract_first()
item["info"] = i.xpath(".//div[@class='Intr']/p/text()").extract_first()
item["collection"] = response.meta["collection"]
yield item
# 提取下一页的地址
if i := response.xpath("//a[text()='查看下一个月']/@href").extract_first():
next_url = base_url + i
# 发送新的请求
yield scrapy.Request(
url=next_url,
callback=self.parse
)
middlewares.py
由于发售表的特殊性,每个月都可能会有新的游戏更新,因此在spider中设置结束条件较为困难,可以将结束条件放置到middlewares中,定义一个结束标志
def process_response(self, request, response, spider):
game_count = len(response.xpath("//li[@class='lx1']"))
if not game_count:
raise IgnoreRequest("已经结束了")
pipelines.py
获取到数据以后,还需要对数据进行清洗,去除掉不需要的部分,以及多余的空白符,为此要专门定义一个数据清理的pipeline
def process_item(self, item, spider):
item["publish_time"] = item["publish_time"].replace("发行日期:", "")
item["producer"] = item["producer"].replace("制作发行: ", "")
return item
得到了所需数据以后,要将数据保存到mongo数据库中,因此要添加对应的pipeline,用于保存数据进入到数据库
def process_item(self, item, spider):
collection = item["collection"]
self.db[collection].insert_one(dict(item))
return item
完整程序
程序运行效果展示
截止到目前为止,我们的程序就已经满足了所需的所有功能。如果还需要添加更多功能,可能可以考虑再保存一份数据进入到mysql数据库,爬取游戏的图片保存到文件中等等,爬虫所能实现的功能相对来说就只有这么多。后续如果考虑再做一个界面展示数据,或者对数据进行分析,可视化等等,就并非是爬虫程序本身的功能了,但是如果有需要的话,也可以这样做
完整的程序以及使用说明已经上传至github,这里是该项目github链接地址
如需下载,可以通过git直接下载
git clone https://github.com/sagegrass/spider02.git
多数爬虫程序很快就会由于对方地址和服务变化导致失效,因此无法保证当你看到这篇文章时,文中的程序仍然可以使用。如果文中的程序已失效,需要自行或者求助他人进行重写
另外,切勿将爬虫程序用于非法用途,或者错误的滥用造成对方网站的负担,谢谢!



