当前位置: 首页 > 科技观察

人人都知道数据采集——Scrapy爬虫框架介绍

时间:2023-03-12 19:37:19 科技观察

在这个“大数据”和“人工智能”时代,数据分析和挖掘逐渐成为互联网从业者的必备技能。本文介绍使用轻量级爬虫框架scrapy进行数据采集的基本方法。一、scrapy简介Scrapy是一个用Python编写的异步爬虫框架。它基于Twisted,运行于Linux/Windows/MacOS等环境。具有速度快、扩展性强、使用方便等特点。即使是新手也能很快掌握并编写出所需的爬虫程序。scrapy可以在本地运行,也可以部署到云端(scrapyd),实现真正的生产级数据采集系统。我们通过一个例子来学习如何使用scrapy从网上收集数据。“博客园”是一个技术综合信息网站。这次我们的任务是收集书名、摘要、发布日期、阅读数量,共4个字段。最终结果是包含所有4个字段的文本文件。如图:最终得到的数据如下。每条记录有四行,分别是标题、阅读次数、发布时间、文章摘要:2、安装scrapy下面看看如何安装scrapy。首先,你的系统中必须有Python和pip。本文以最常见的Python2.7.5版本为例。pip是Python的包管理工具,在Linux系统中一般默认安装。在命令行输入以下命令执行:sudopipinstallscrapy-ihttp://pypi.douban.com/simple–trusted-host=pypi.douban.compip会从豆瓣软件源下载并安装scrapy,以及所有依赖包将自动下载并安装。“sudo”表示以超级用户权限执行此命令。所有进度条走完后,如果提示类似“SuccessfullyinstalledTwisted,scrapy...”,则表示安装成功。3.scrapy交互环境scrapy还提供了一个可以交互运行的Shell,可以让我们方便的测试解析规则。scrapy安装成功后,在命令行输入scrapyshell,启动scrapy的交互环境。scrapyshell的提示是三个大于号>>>,表示可以接收命令。我们先使用fetch()方法获取首页的内容:>>>fetch(“https://www.cnblogs.com/cate/mysql/”)如果屏幕上显示如下输出,说明网页内容已获取。2017-09-0407:46:55[scrapy.core.engine]INFO:Spideropened2017-09-0407:46:55[scrapy.core.engine]DEBUG:Crawled(200)(referer:None)获取的response会存储在response对象中。该对象的status属性表示HTTP响应状态,正常情况下为200。>>>printresponse.status200text属性表示返回的内容数据,从中可以解析出需要的内容。>>>printresponse.textu'\r\n\r\n\r\n\r\n\r\n\r\nMySQL–\u7f51\u7ad9\u5206\u7c7b–\u535a\u5ba2\u56ed\r\n'可以看作是一堆乱七八糟的HTML代码,无法直观的找到我们需要的数据。这时候我们可以通过浏览器的“开发者工具”获取指定数据的DOM路径。用浏览器打开网页https://www.cnblogs.com/cate/mysql/后,按F12键启动开发者工具,快速定位到指定内容。可以看到我们需要的4个字段都在/body/div(id="wrapper")/div(id="main")/div(id="post_list")/div(class="post_item")/div(class="post_item_body")/,每个“post_item_body”包含一篇文章的标题、摘要、发布日期、阅读次数。我们先获取所有的“post_item_body”,然后从中解析出每篇文章的4个字段。>>>post_item_body=response.xpath("//div[@id='wrapper']/div[@id='main']/div[@id='post_list']/div[@class='post_item']/div[@class='post_item_body']")>>>len(post_item_body)20len(post_item_body)20response的xpath方法可以使用xpath解析器获取DOM数据。xpath的语法可以参考官网文档。可以看到我们获取了首页所有20篇文章的post_item_body。那么如何提取每篇文章的这4个字段呢?我们以第一篇文章为例。先取第一个post_item_body:>>>first_article=post_item_body[0]标题在h3/apost_item_body节点下,xpath方法中text()的作用是获取当前节点的文本,extract_first()而strip()then就是提取xpath表达式中的节点,过滤掉前后的空格和回车:>>>article_title=first_article.xpath(“h3/a/text()”).extract_first().strip()>>>printarticle_titleMysql表操作和索引操作,然后用类似的方式提取文章摘要:>>>article_summary=first_article.xpath("p[@class='post_item_summary']/text()").extract_first().strip()>>>printarticle_summary表操作:1.建表:createtableifnotexiststable_name(字段定义);example:createtableifnotexistsuser(idintauto_increment,unamevarchar(20),addressvarch...提取post_item_foot时,发现提取了两组内容,***组为空内容,第二组为文本“publishedonXXX”。我们提取第二组内容并过滤掉“postedon”字样:>>>post_date=first_article.xpath("div[@class='post_item_foot']/text()").extract()[1]。split("发表于")[1].strip()>>>printpost_date2017-09-0318:13***提取阅读数:>>>article_view=first_article.xpath("div[@class='post_item_foot']/span[@class='article_view']/a/text()").extract_first()>>>printarticle_view阅读(6)很多人认为xpath方法中的规则过于复杂。其实只要稍微了解一下HTML文件的DOM结构,掌握xpath的提取规则还是比较容易的。幸运的是,scrapyshell允许我们反复尝试解析DOM文件。测试成功的xpath表达式可以直接在项目中使用。4、创建一个scrapy项目scrapyshell只适用于测试目标网站能否正常采集,以及采集后如何分析。在实际做项目的时候,需要从头开始构建一个scrapy项目。输入以下命令退出scrapyshell,返回Linux命令行:>>>exit()假设我们的项目名为cnblogs_scrapy,可以通过以下命令创建一个scrapy项目:scrapystartprojectcnblogs_scrapy会自动生成目录和文件以下结构:|–cnblogs_scrapy||–__init__.py||–items.py||–middlewares.py||–pipelines.py||–settings.py|`–spiders|`–__init__.py`–scrapy.cfg五、分析我们需要改变三个存放存储的地方:1.在spiders目录下新建一个文件cnblogs_mysql.py,内容如下:#-*-coding:utf-8-*-importscrapyimportsysreload(sys)sys.setdefaultencoding("utf8")classCnblogsMySQL(scrapy.Spider):#爬虫的名字必须有这个变量name='cnblogs_mysql'page_index=1#起始地址必须有这个变量start_urls=['https://www.cnblogs.com/cate/mysql/'+str(page_index),]defparse(self,response):post_items=response.xpath("//div[@id='wrapper']/div[@id='main']/div[@id='post_list']/div[@class='post_item']/div[@class='post_item_body']")forpost_item_bodyinpost_items:yield{'article_title':post_item_body.xpath("h3/a/text()").extract_first()。strip(),'article_summary':post_item_body.xpath("p[@class='post_item_summary']/text()").extract_first().strip(),'post_date':post_item_body.xpath("div[@class='post_item_foot']/text()").extract()[1].strip(),'article_view':post_item_body.xpath("div[@class='post_item_foot']/span[@class='article_view']/a/text()").extract_first().strip()}next_page_url=Noneself.page_index+=1ifself.page_index<=20:next_page_url="https://www.cnblogs.com/cate/mysql/"+str(self.page_index)else:next_page_url=Noneifnext_page_urlisnotNone:yieldscrapy.Request(response.urljoin(next_page_url))这是我们的爬虫,其中name和start_urls这两个变量必须存在。parse方法的作用是将响应内容解析成我们需要的数据。parse中的for循环从每个页面中提取20篇文章。解析提取完成后,通过yield将结果丢给管道存储。2.修改pipelines.py文件,内容如下:#-*-coding:utf-8-*-#Defineyouritempipelineshere##Don'tforgettoaddyourpipelinetotheITEM_PIPELINESsetting#See:http://doc.scrapy.org/en/latest/topics/item-pipeline.htmlclassCnblogsScrapyPipeline(object):defopen_spider(self,spider):self.fp=open("data.list","w")defclose_spider(self,spider):self.fp.close()defprocess_item(self,item,spider):self.fp.write(item["article_title"]+"\n")self.fp.write(item["article_view"]+"\n")self.fp.write(item["post_date"]+"\n")self.fp.write(item["article_summary"]+"\n\n")returnitem可以看到有3个方法。这三个方法都是继承自基类。open_spider/close_spider分别在爬虫启动和结束时执行,一般用于初始化和结束。每次蜘蛛解析数据并让出处理解析结果时,都会执行process_item。上面管道的作用是将每条记录存储在一个文件中。当然,内容也可以通过管道存储在数据库或者其他地方。3.配置pipeline注意,只有这个pipeline文件是不行的,需要在配置文件中声明pipeline给scrapy。同目录下有一个settings.py文件,添加如下内容:ITEM_PIPELINES={'cnblogs_scrapy.pipelines.CnblogsScrapyPipeline':300,}后面的数字是pipeline的权重。如果一个爬虫有多个管道,每个管道的执行顺序是由这个权重决定的。修改完成并保存后,回到cnblogs_scrapy的上层目录,输入以下命令启动爬虫:scrapycrawlcnblogs_mysql处理后的所有信息都会输出到屏幕上。结束后会在当前目录下生成一个名为data.list的文件,里面存放了本次采集到的所有数据。6、翻页在cnblogs_mysql.py的parse方法中有一个next_page_url变量。一般这个变量的内容应该是当前页面的下一页的URL。当然也可以通过解析页面获取URL。获取到下一页的URL后,使用scrapy.Request发起新的请求。为了简单起见,本文规定直接拼接URL只采集前20页数据。7、在用scrapy发送请求之前,也可以自己构造一个Request,这样就可以假装是真正的访问,避免被屏蔽。一般有修改User-Agent、随机采集时间、随机代理IP等方法。scrapy项目可以直接运行,也可以部署在云端进行批量采集和监控。云部署需要使用scrapyd,操作非常简单。如有需要,可以参考官网文档。【本文为栏目组织《奇安科技》原创文章,转载请微信公众号(bigsec)联系原作者】点此查看更多本作者好文