手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

Irene181 等级 1180 0 0

大家好,我是杯酒先生,这是我第一次写这种分享项目的文章,可能很水,很不全面,而且肯定存在说错的地方,希望大家可以评论里加以指点,不胜感激!

一、前言

网络爬虫(又称为网页蜘蛛,网络机器人),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。------百度百科

说人话就是,爬虫是用来海量规则化获取数据,然后进行处理和运用,在大数据、金融、机器学习等等方面都是必须的支撑条件之一。

目前在一线城市中,爬虫的岗位薪资待遇都是比较客观的,之后提升到中、高级爬虫工程师,数据分析师、大数据开发岗位等,都是很好的过渡。

二、项目目标

本此介绍的项目其实不用想的太过复杂,最终要实现的目标也就是将帖子的每条评论爬取到数据库中,并且做到可以更新数据,防止重复爬取,反爬等措施。

三、项目准备

这部分主要是介绍本文需要用到的工具,涉及的库,网页等信息等

软件:PyCharm

需要的库:Scrapy, selenium, pymongo, user_agent,datetime

目标网站:

http://bbs.foodmate.net

插件:chromedriver(版本要对)

四、项目分析

1、确定爬取网站的结构

简而言之:确定网站的加载方式,怎样才能正确的一级一级的进入到帖子中抓取数据,使用什么格式保存数据等。

其次,观察网站的层级结构,也就是说,怎么根据板块,一点点进入到帖子页面中,这对本次爬虫任务非常重要,也是主要编写代码的部分。

2、如何选择合适的方式爬取数据?

目前我知道的爬虫方法大概有如下(不全,但是比较常用):

1)request框架:运用这个http库可以很灵活的爬取需要的数据,简单但是过程稍微繁琐,并且可以配合抓包工具对数据进行获取。但是需要确定headers头以及相应的请求参数,否则无法获取数据;很多app爬取、图片视频爬取随爬随停,比较轻量灵活,并且高并发与分布式部署也非常灵活,对于功能可以更好实现。

2)scrapy框架:scrapy框架可以说是爬虫最常用,最好用的爬虫框架了,优点很多:scrapy 是异步的;采取可读性更强的 xpath 代替正则;强大的统计和 log 系统;同时在不同的 url 上爬行;支持 shell 方式,方便独立调试;支持写 middleware方便写一些统一的过滤器;可以通过管道的方式存入数据库等等。这也是本次文章所要介绍的框架(结合selenium库)。

五、项目实现

1、第一步:确定网站类型

首先解释一下是什么意思,看什么网站,首先要看网站的加载方式,是静态加载,还是动态加载(js加载),还是别的方式;根据不一样的加载方式需要不同的办法应对。然后我们观察今天爬取的网站,发现这是一个有年代感的论坛,首先猜测是静态加载的网站;我们开启组织 js 加载的插件,如下图所示。

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

刷新之后发现确实是静态网站(如果可以正常加载基本都是静态加载的)。

2、第二步:确定层级关系

其次,我们今天要爬取的网站是食品论坛网站,是静态加载的网站,在之前分析的时候已经了解了,然后是层级结构:

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

大概是上面的流程,总共有三级递进访问,之后到达帖子页面,如下图所示。

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

部分代码展示:

一级界面:

`def parse(self, response):` `self.logger.info("已进入网页!")` `self.logger.info("正在获取版块列表!")` `column_path_list = response.css('#ct > div.mn > div:nth-child(2) > div')[:-1]` `for column_path in column_path_list:` `col_paths = column_path.css('div > table > tbody > tr > td > div > a').xpath('@href').extract()` `for path in col_paths:` `block_url = response.urljoin(path)` `yield scrapy.Request(` `url=block_url,` `callback=self.get_next_path,` `)`

二级界面:

`def get_next_path(self, response):` `self.logger.info("已进入版块!")` `self.logger.info("正在获取文章列表!")` `if response.url == 'http://www.foodmate.net/know/':` `pass` `else:` `try:` `nums = response.css('#fd_page_bottom > div > label > span::text').extract_first().split(' ')[-2]` `except:` `nums = 1` `for num in range(1, int(nums) + 1):` `tbody_list = response.css('#threadlisttableid > tbody')` `for tbody in tbody_list:` `if 'normalthread' in str(tbody):` `item = LunTanItem()` `item['article_url'] = response.urljoin(` `tbody.css('* > tr > th > a.s.xst').xpath('@href').extract_first())` `item['type'] = response.css(` `'#ct > div > div.bm.bml.pbn > div.bm_h.cl > h1 > a::text').extract_first()` `item['title'] = tbody.css('* > tr > th > a.s.xst::text').extract_first()` `item['spider_type'] = "论坛"` `item['source'] = "食品论坛"` `if item['article_url'] != 'http://bbs.foodmate.net/':` `yield scrapy.Request(` `url=item['article_url'],` `callback=self.get_data,` `meta={'item': item, 'content_info': []}` `)` `try:` `callback_url = response.css('#fd_page_bottom > div > a.nxt').xpath('@href').extract_first()` `callback_url = response.urljoin(callback_url)` `yield scrapy.Request(` `url=callback_url,` `callback=self.get_next_path,` `)` `except IndexError:` `pass`

三级界面:

`def get_data(self, response):` `self.logger.info("正在爬取论坛数据!")` `item = response.meta['item']` `content_list = []` `divs = response.xpath('//*[@id="postlist"]/div')` `user_name = response.css('div > div.pi > div:nth-child(1) > a::text').extract()` `publish_time = response.css('div.authi > em::text').extract()` `floor = divs.css('* strong> a> em::text').extract()` `s_id = divs.xpath('@id').extract()` `for i in range(len(divs) - 1):` `content = ''` `try:` `strong = response.css('#postmessage_' + s_id[i].split('_')[-1] + '').xpath('string(.)').extract()` `for s in strong:` `content += s.split(';')[-1].lstrip('\r\n')` `datas = dict(content=content,  # 内容` `reply_id=0,  # 回复的楼层,默认0` `user_name=user_name[i],  # ⽤户名` `publish_time=publish_time[i].split('于 ')[-1],  # %Y-%m-%d %H:%M:%S'` `id='#' + floor[i],  # 楼层` `)` `content_list.append(datas)` `except IndexError:` `pass` `item['content_info'] = response.meta['content_info']` `item['scrawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')` `item['content_info'] += content_list` `data_url = response.css('#ct > div.pgbtn > a').xpath('@href').extract_first()` `if data_url != None:` `data_url = response.urljoin(data_url)` `yield scrapy.Request(` `url=data_url,` `callback=self.get_data,` `meta={'item': item, 'content_info': item['content_info']}` `)` `else:` `item['scrawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')` `self.logger.info("正在存储!")` `print('储存成功')` `yield item`

3、第三步:确定爬取方法

由于是静态网页,首先决定采用的是scrapy框架直接获取数据,并且通过前期测试发现方法确实可行,不过当时年少轻狂,小看了网站的保护措施,由于耐心有限,没有加上定时器限制爬取速度,导致我被网站加了限制,并且网站由静态加载网页变为:动态加载网页验证算法之后再进入到该网页,直接访问会被后台拒绝。

但是这种问题怎么会难道我这小聪明,经过我短暂地思考(1天),我将方案改为scrapy框架 + selenium库的方法,通过调用chromedriver,模拟访问网站,等网站加载完了再爬取不就完了,后续证明这个方法确实可行,并且效率也不错。

实现部分代码如下:

`def process_request(self, request, spider):` `chrome_options = Options()` `chrome_options.add_argument('--headless')  # 使用无头谷歌浏览器模式` `chrome_options.add_argument('--disable-gpu')` `chrome_options.add_argument('--no-sandbox')` `# 指定谷歌浏览器路径` `self.driver = webdriver.Chrome(chrome_options=chrome_options,` `executable_path='E:/pycharm/workspace/爬虫/scrapy/chromedriver')` `if request.url != 'http://bbs.foodmate.net/':` `self.driver.get(request.url)` `html = self.driver.page_source` `time.sleep(1)` `self.driver.quit()` `return scrapy.http.HtmlResponse(url=request.url, body=html.encode('utf-8'), encoding='utf-8',` `request=request)`

4、第四步:确定爬取数据的储存格式

这部分不用多说,根据自己需求,将需要爬取的数据格式设置在items.py中。在工程中引用该格式保存即可:

`class LunTanItem(scrapy.Item):` `"""` `论坛字段` `"""` `title = Field()  # str: 字符类型 | 论坛标题` `content_info = Field()  # str: list类型 | 类型list: [LunTanContentInfoItem1, LunTanContentInfoItem2]` `article_url = Field()  # str: url | 文章链接` `scrawl_time = Field()  # str: 时间格式 参照如下格式 2019-08-01 10:20:00 | 数据爬取时间` `source = Field()  # str: 字符类型 | 论坛名称 eg: 未名BBS, 水木社区, 天涯论坛` `type = Field()  # str: 字符类型 | 板块类型 eg: '财经', '体育', '社会'` `spider_type = Field()  # str: forum | 只能写 'forum'`

5、第五步:确定保存数据库

本次项目选择保存的数据库为mongodb,由于是非关系型数据库,优点显而易见,对格式要求没有那么高,可以灵活储存多维数据,一般是爬虫优选数据库(不要和我说redis,会了我也用,主要是不会)

代码:

`import pymongo``class FMPipeline():` `def __init__(self):` `super(FMPipeline, self).__init__()` `# client = pymongo.MongoClient('139.217.92.75')` `client = pymongo.MongoClient('localhost')` `db = client.scrapy_FM` `self.collection = db.FM` `def process_item(self, item, spider):` `query = {` `'article_url': item['article_url']` `}` `self.collection.update_one(query, {"$set": dict(item)}, upsert=True)` `return item`

这时,有聪明的盆友就会问:如果运行两次爬取到了一样的数据怎么办呢?(换句话说就是查重功能)

这个问题之前我也没有考虑,后来在我询问大佬的过程中知道了,在我们存数据的时候就已经做完这件事了,就是这句:

`query = {` `'article_url': item['article_url']``}``self.collection.update_one(query, {"$set": dict(item)}, upsert=True)`

通过帖子的链接确定是否有数据爬取重复,如果重复可以理解为将其覆盖,这样也可以做到更新数据。

6、其他设置

像多线程、headers头,管道传输顺序等问题,都在settings.py文件中设置,具体可以参考小编的项目去看,这里不再赘述。

七、效果展示

1、点击运行,结果显示在控制台,如下图所示。

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

2、中间会一直向队列中堆很多帖子的爬取任务,然后多线程处理,我设置的是16线程,速度还是很可观的。

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

3、数据库数据展示:

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

content_info中存放着每个帖子的全部留言以及相关用户的公开信息。

八、总结

1、这篇文章主要给大家介绍了食品网站的数据采集和存储过程,详解了如何分析网页结构、爬虫策略、网站类型、层级关系、爬虫方法和数据存储过程,最终实现将帖子的每条评论爬取到数据库中,并且做到可以更新数据,防止重复爬取,反爬等,干货满满。

2、本次项目总的来说,不是特别难搞,只要思路对了,找到了数据规则,爬起来可以说易如反掌,觉得难只是之前没有完整走过流程,有了这次比较水的介绍,希望能对你有所帮助,那将是我最大的荣幸。

3、遇到问题首先想的不是问同事,朋友,老师,而是去谷歌,百度,看有没有相似的情况,看别人的经历,一定要学会自己发现问题,思考问题,解决问题,这对于之后工作有非常大的帮助(我之前就被说过还没有脱离学生时代,就是我喜欢问同事),等网上查询了一定资料了,还是没有头绪,再去问别人,别人也会比较愿意帮助你的~

我是杯酒先生,最后分享我的座右铭给大家:保持独立思考,不卑不亢不怂。

最后需要本文项目代码的小伙伴,请在公众号后台回复“食品论坛”关键字进行获取,如果在运行过程中有遇到任何问题,请随时留言或者加小编好友,小编看到会帮助大家解决bug噢!

想要学习更多网络爬虫知识,请点击阅读原文前往爬虫网站。

**-----**------**-----**---**** End **-----**--------**-----**-****

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

往期精彩文章推荐:

手把手教你用Scrapy爬虫框架爬取食品论坛数据并存入数据库

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/YZ76EkZGMWO35nt4qtTNFQ,如有侵权,请联系删除。

收藏
评论区

相关推荐

使用Scrapy网络爬虫框架小试牛刀
前言这次咱们来玩一个在Python中很牛叉的爬虫框架——Scrapy。 scrapy 介绍标准介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,非常出名,非常强悍。所谓的框架就是一个已经被集成了各种功能(高性能异步下载,队列,分布式,解析,持久化等)的具有很强通用性的项目模板。对于框架的学习,重点是要学习其框架的特性、各个功能的
(原创)Scrapy爬取美女图片续集
      上一篇咱们讲解了Scrapy的工作机制和如何使用Scrapy爬取美女图片,而今天接着讲解Scrapy爬取美女图片,不过采取了不同的方式和代码实现,对Scrapy的功能进行更深入的运用。 ![](https://oscimg.oschina.net/oscnet/495475f784c4eb6eadac4fb32e103808c26.jpg)
Crawlscrapy分布式爬虫
1.概念:多台机器上可以执行同一个爬虫程序,实现网站数据的分布爬取 2.原生的scrapy是不可以实现分布式式爬虫   a)调度器无法共享   b)管道无法共享 3.scrapy-redis 组件:专门为scrapy开发的一套组件,该组件可以让scrapy实现分布式   a)pip install scrapy-redis 4.分布式爬取的流程:
Python Scrapy 实战
Python Scrapy ============= 什么是爬虫? ------ 网络爬虫(英语:web crawler),也叫网络蜘蛛(spider),是一种用来自动浏览万维网的网络机器人。其目的一般为编纂网络索引。 Python 爬虫 --------- 在爬虫领域,Python几乎是霸主地位,将网络一切数据作为资源,通过自动化程序进行有针对性
Python scrapy爬取带验证码的列表数据
首先所需要的环境:(我用的是Python2的,可以选择python3,具体遇到的问题自行解决,目前我这边几百万的数据量爬取) 环境:Python 2.7.10 Scrapy Scrapy 1.5.0 第三方库: PyMySQL==0.8.0Scrapy==1.5.0pytesseract==0.2.0pip==10.0.1Pil
Python之scrapy实现的爬虫,百度贴吧的自动签到和自动发帖、自动回帖
百度贴吧Crawler =========== [![Travis branch](https://img.shields.io/travis/rust-lang/rust/master.svg)](https://gitee.com/changleibox/TiebaCrawler) 实现百度贴吧的自动签到和自动发帖、自动回帖 实现Cookies
Python爬虫教程
本篇是介绍在 Anaconda 环境下,创建 Scrapy 爬虫框架项目的步骤,且介绍比较详细 Python爬虫教程-31-创建 Scrapy 爬虫框架项目 ------------------------------ * 首先说一下,本篇是在 Anaconda 环境下,所以如果没有安装 Anaconda 请先到官网下载安装 * Anaconda
Scrapy
scrapy -->CrawlSpider 介绍 ------------------------ * * * 1、首先,通过crawl 模板新建爬虫: -------------------- scrapy genspider -t crawl lagou www.lagou.com ### 创建出来的爬虫文件lagou.py: ![](
Scrapy_redis
简介 scrapy\_redis是一个基于Redis的Scrapy组件,用于scrapy项目的分布式部署和开发 你可以启动多个spider对象,互相之间共享有一个redis的request队列,最适合多个域名的广泛内容的爬取 特点 分布式爬取 分布式数据处理 爬取到的item数据被推送到redis中,这意味着你可以启动尽可能多的item处理程序
Scrapy使用入门及爬虫代理配置
本文通过一个简单的项目实现Scrapy采集流程。希望通过该项目对Scrapy的使用方法和框架能够有帮助。 ### 1\. 工作流程 重点流程如下: * 创建一个Scrapy项目。 * 创建一个爬虫来抓取网站和处理数据。 * 通过命令行将采集的内容进行分析。 * 将分析的数据保存到MongoDB数据库。 ### 2\. 准备环境 安装
Scrapy框架
\[TOC\] 1\. Scrapy介绍 ============ 1.1. Scrapy框架 ------------- Scrapy是用纯Python实现一个为了爬取网站数据、提取结构性数据而编写的应用框架,用途非常广泛。 ![](http://ccszt.com.cn/python/%E7%88%AC%E8%99%AB/file/images/
Scrapy框架之分布式操作
一、分布式爬虫介绍 ---------   分布式爬虫概念:多台机器上执行同一个爬虫程序,实现网站数据的分布爬取。 ### 1、原生的Scrapy无法实现分布式爬虫的原因? * **调度器无法在多台机器间共享**:因为多台机器上部署的scrapy会各自拥有各自的调度器,这样就使得多台机器无法分配start\_urls列表中的url。 * **管
Scrapy爬取遇到的一点点问题
学了大概一个月Scrapy,自己写了些东东,遇到很多问题,这几天心情也不大好,小媳妇人也不舒服,休假了,自己研究了很久,有些眉目了 利用scrapy 框架爬取慕课网的一些信息 步骤一:新建项目     scrapy startproject muke     进入muke     scrapy genspider mukewang imooc.co
Scrapy爬虫框架下执行爬虫的方法
  在使用Scrapy框架进行爬虫时,执行爬虫文件的方法是 scrapy crawl xxx ,其中 xxx 是爬虫文件名。   但是,当我们在建立了多个文件时,使用上面的命令时会比较繁琐麻烦,我们就可以使用下述方法同时完成爬虫文件的执行。   第一种,在scrapy框架下建立一个运行文件,如 run.py ,在文件中建立一个列表,列表为爬虫的执行命令,
Scrapy笔记(1)
Scrapy笔记01- 入门篇 ===============   Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘, 信息处理或存储历史数据等一系列的程序中。其最初是为了页面抓取(更确切来说,网络抓取)所设计的, 也可以应用在获取API所返回的数据(比如Web Services)或者通用的网络爬虫。   Scr