本文通过案例分析介绍如何通过Python中的Scrapy库进行网页数据爬取,内含代码分析,建议边阅读边实践,目录如下:
1. Scrapy简介2. 编写第一个网页爬取代码 2.1 安装Scrapy库 2.2 使用Scrapy Shell 进行快速试验 2.3 编写自定义Spider类3. 案例实践 3.1 Scrapy Shell调试代码 3.2 创建Spider类
1. Scrapy 简介
Scrapy是一个用于大规模网络数据爬取的Python框架。它提供了一系列工具用于高效地爬取网站数据,并且可以根据需要进行数据处理,并保存为结构化信息。
由于互联网的多样性,并没有“一刀切”的方法爬取网站数据,因此许多时候都采取临时的方法。当为一个小型任务编写代码时,会创建一个数据爬取的框架,Scrapy就是这样的框架。
2. 编写第一个网页爬取代码
以下将逐步分析如何应用Scrapy编写一个网页爬取代码。
2.1 安装Scrapy库
Scrapy库支持Python2.0和3.0,建议使用Anaconda进行安装,也可以直接pip安装。
若使用Anaconda进行安装,如下:
conda install -c conda-forge scrapy
也可直接使用pip命令安装,如下:
pip install scrapy
注:本文在Python3.0环境中使用Scrapy
2.2 使用Scrapy Shell 进行快速试验
2017年夏,美剧《权力的游戏》第7季播放,在Reddit上形成了话题专区。以下将使用Scrapy Shell对关于权游的讨论话题、评论数量、相关用户等数据进行爬取。
权游话题讨论专区网址为:https://www.reddit.com/r/gameofthrones/ ,这也是用于爬取的URL。
注 :Reddit是一个娱乐、社交及新闻网站,注册用户可以将文字或链接在网站上发布,使它基本上成为了一个电子布告栏系统。注册用户可以对这些帖子进行投票,结果将被用来进行排名和决定它在首页或子页的位置。网站上的内容分类被称为“subreddit”。(来自维基百科)
关于Scrapy 终端(Scrapy Shell)
Scrapy终端是一个交互终端,供您在未启动spider的情况下尝试及调试您的爬取代码。 该终端是用来测试XPath或CSS表达式,查看他们的工作方式及从爬取的网页中提取的数据。 在编写您的spider时,该终端提供了交互性测试您的表达式代码的功能,免去了每次修改后运行spider的麻烦。(来自Scrapy 0.24.6 文档)
在cmd中启动Scrapy Shell:
scrapy shell
爬取权游话题网页:
fetch('https://www.reddit.com/r/gameofthrones/')
当使用Scrapy进行爬取时,会返回一个response对象,里面包含了下载的信息,以下查看下载的内容:
view(response)
同时会打开已下载的网页:
以下查看下载网页的原始内容:
print(response.text)
显示的内容非常多,以下为需要从中提取的内容:
每篇文章的标题
获得的投票数量
获得的评论数量
文章发布的时间
2.2.1 提取文章标题
Scrapy基于css采集器提供了多种从HTML源码中提取信息,比如class、id等。首先需要分析文章标题对应的css采集器,在网页上右键打开“检查”:
这会打开浏览器的开发者工具,从中找到title,位于
标签中,以此提取出response对象中的标题信息:
response.css(".title::text").extract()
此处,response.css()方法基于css采集器传递给它的内容进行抽取。由于是css,title前需要加.。并且,::text告诉scraper只提取匹配元素中的text内容,这样做是因为scraper直接以HTML源代码的形式返回匹配的元素内容,比如:
2.2.2 提取投票数量
此处,可以发现有三个得分信息,进一步查看网页内容,可以发现score unvoted对应的是投票数量。
当超过两个采集器用来定义一个元素时,它们都需要用来提取内容,而且都是css类,所以都需要使用.。以下尝试提取投票数量:
response.css(".score.unvoted").extract_first()
对比网页信息,可以看出提取的投票数量是正确的,进一步需要使用::text只提取其中的数量,而不是整个vote元素。
response.css(".score.unvoted::text").extract()
2.2.3 提取评论数量
与以上两次提取类似,提取评论数量:
response.css(".comments::text").extract()
2.2.4 提取文章发布时间
按照以上逻辑提取文章发布时间:
response.css("time::text").extract()
注:此处time不是css类,不需要加.
可以发现提取的内容为文章发布的相对时间,再次查看HTML源代码:
可以发现time中title属性中包括具体的日期和时间,因此使用.attr()提取获取匹配元素中指定属性的值:
response.css("time::attr(title)").extract()
2.3 编写自定义Spider类
Spider类时用于爬取网站内容的程序。由于网站设计的多样性,在大规模爬取数据时,需要为不同的网站编写自定义的Spider类,同时需要编写代码将爬取的内容转化为结构化格式,比如csv、json、excel等,这些都包含在Scrapy的内置功能中。
2.3.1 创建Scrapy项目
现在需要退出Scrapy Shell,再创建一个新的Scrapy项目:
scrapy startproject firstone
以上创建了firstone文件夹,可以查看文件夹结构:
tree firstone /F
此处,最重要的两个文件是:
settings.py——包含了项目的设置信息,可以进行一系列操作
spider/——该文件夹存储所有的自定义Spider类,每次运行一个Spider类,Scrapy会自动在此文件夹中查找并运行
2.3.2 创建Spider类
下面需要进入firstone文件夹,并创建一个spider类:redditbt
scrapy genspider redditbot www.reddit.com/r/gameofthrones/
以上,在spider/文件夹中创建了redditbot.py文件,其内部包含了一个基本的模板:
此处,关于以上模板中的内容:
name:Spider类的名字
allowed_domains:允许此Spider类爬取的网页地址,不属于此域名的URL无法爬取
parse(self,response):当成功爬取到一个URL时,会调用此函数,而且这里的response对象和前面提到的一致
每次爬取成功之后,都会调用parse()函数,这里就是编写提取逻辑的地方。现在添加之前试验过的提取逻辑,包括提取标题、投票数量、评论数量等。
def parse(self, response): # 使用css采集器提取内容 titles = response.css('.title.may-blank::text').extract() votes = response.css('.score.unvoted::text').extract() times = response.css('time::attr(title)').extract() comments = response.css('.comments::text').extract() # 将提取的内容按行排序 for item in zip(titles, votes, times, comments): # 创建字典存储爬取的信息 scraped_info = { 'title': item[0], 'vote': item[1], 'created_at': item[2], 'comments': item[3], } # 将爬取的信息传递给Scrapy yield scraped_info
此处,yield scraped_info将爬取的信息传递给Scrapy,后者将依次处理信息并存储。
保存redditbot.py文件,打开cmd,进入firstone文件夹,运行这个Spider类:
scrapy crawl redditbot
以上输出信息显示所有数据已经下载,并且存放在字典中。
2.3.3 将爬取的数据保存为csv格式
Scrapy可以将爬取的内容导出为csv、json等多种格式,现在打开settins.py文件,并且添加以下信息:
# 导出为csv文件FEED_FORMAT = "csv"FEED_URI = "reddit.csv"
关于以上信息:
FEED_FORMAT:定义输出文件的格式,目前支持的格式有csv、json、json lines、xml
FEED_URI:输出文件的路径
再次运行这个Spider类:
scrapy crawl redditbot
这会在firstone文件夹中输出reddit.csv文件,内容如下:
现在已经成功地创建了一个系统,可以爬取网页内容,从中提取目标信息,并且保存为结构化格式。下面将进行另外一个案例实践。
3. 案例实践
Techcrunch关于技术产品的博客网站,并且提供了自己的RSS源码: https://techcrunch.com/feed/。Scrapy的一大特点就是能够轻松处理XML数据,下面就要从Techcrunch的RSS源码中爬取信息。
查看Techcrunch的RSS源码,下面是需要提取的信息:
从以上页面可以看出:
每篇文章的信息显示在标签中
文章标题保存在
标签中文章链接保存在标签中
发布日期保存在中
作者姓名保存在中
关于XPath和XML
XPath是用来定义XML文档的语法,可以用来遍历一个XML文档,并且遵循层次结构。
3.1 Scrapy Shell调试代码
和第2部分类似,首先在Scrapy Shell中调试代码。
爬取网页:
fetch('https://techcrunch.com/feed/')
3.1.1 提取文章标题、链接及发布日期信息
和response.css()方法类似,response.xpath()方法用于处理XPath,现在提取文章标题信息:
response.xpath("//item/title").extract_first()
输出结果较多,进一步需要提取出标题部分:
response.xpath("//item/title/text()").extract_first()
此处text()相当于CSS采集器中::text,关于XPath//item/title/text()是指,查找item元素,从text子元素中提取text部分。
类似的,对于链接以及发布日期的XPath提取:
Link-//item/link/text()
Date of publishing-//item/pubDate/text()
3.1.2 提取作者姓名信息
提取作者信息如下:
response.xpath("//item/creator/text()").extract_first()
并没有得到结果,因此查看标签:
标签含有dc:,因此使用XPath不能提取,而且姓名部分含有![CDATA[]]相关文本。这些是XML的命名空间,需要先删除这些命名空间再提取内容:
response.selector.remove_namespaces()
再次提取作者姓名信息:
response.xpath("//item/creator/text()").extract_first()
3.2 创建Spider类
代码调试完成后,从Scrapy Shell退出,进入firstone文件夹,创建一个新的Spider类:
Scrapy genspider techcrunch techcrunch.com/feed/
接着,将调试过的代码添加到techcrunch.py文件中,完整的代码如下:
import scrapyclass TechcrunchSpider(scrapy.Spider): name = 'techcrunch' allowed_domains = ['techcrunch.com/feed/'] start_urls = ['http://techcrunch.com/feed//'] # 设置输出csv文件的路径 custom_settings = { 'FEED_URI': 'tmp/techcrunch.csv' } def parse(self, response): # 删除XML命名空间 response.selector.remove_namespaces() # 提取文章信息 titles = response.xpath('//item/title/text()').extract() authors = response.xpath('//item/creator/text()').extract() dates = response.xpath('//item/pubDate/text()').extract() links = response.xpath('//item/link/text()').extract() for item in zip(titles, authors, dates, links): scraped_info = { 'title': item[0], 'author': item[1], 'publish_date': item[2], 'link': item[3] } yield scraped_info
注 :以上代码中添加了输出csv文件的路径,如果不添加这部分代码,由于前面在settings.py中设置了输出路径,爬取的数据将被保存到techcrunch.csv文件中。
保存techcrunch.py文件,打开cmd,进入firstone文件夹,运行这个Spider类:
scrapy crawl techcrunch
得到csv文件内容如下:
本文由朝乐门、刘岩翻译,整理并实践后总结,源自Mohd Sanad Zaki Rizvi 在https://www.analyticsvidhya.com/上的文章。
【原文地址】https://www.analyticsvidhya.com/blog/2017/07/web-scraping-in-python-using-scrapy/
【源代码】https://github.com/LemenChao/web-scraping-magic-with-scrapy-and-python
《数据科学理论与实践》
作者:朝乐门
定价:59元
ISBN:9787302480549
图文来自网络、如涉及版权问题,请联系我们以便处理。文章内容纯属作者个人观点,不代表本网观点。