1.环境

python3.8或python3.7

pycharm2021.2

MongoDB

Scrapy

2.信息提取

2.1 创建Scrapy项目

在cmd模式下创建Scrapy项目

# 进入要存放该项目的文件夹下
cd E:\Scrapy Project
# 创建Scrapy项目
scrapy startproject douban
# 进入该项目下,“douban”这个文件夹有一个一级文件夹和二级文件夹,我们只用进入一级文件夹
cd douban
# 创建Spider
scrapy genspider douban_book douban.com

2.2 在Pycharm中打开该项目

打开后,文件树结构为:

注意scrapy.cfg配置文件一定在“douban”一级文件夹下,不然在后面运行该爬虫时,会报错。

2.3 项目目标

1.获取按评分排行的书籍排行榜前任意页的书籍基本信息

2.获取每本书籍的读者评论信息和读者主页链接

3.获取读者的地址

4.写入MongoDB数据库

2.4 初始化数据

初始化rank_url、book_comment_url、headers、allowed_domain等信息,其中name是不能修改的。

刚打开douban_book.py,是如下图所示的界面。

然后修改上述信息。如下图所示。

其中allowed_domain一般情况下不用修改,我这里是测试的时候,发现访问书籍链接地址的时候,其域名是“book.douban.com”,所以添加了进去,其实还有另一种方法,就是在Request函数(很关键的函数)中把域名过滤给关闭掉。

start_urls是在你没有指定访问链接的时候,默认的访问链接,如果有就不会访问该链接。

这里我们有访问的链接,所以我们把start_urls删除了,写上了自己要访问的rank_url,也就是书籍排行榜的访问链接地址,这里有四个,是不同分类的书籍排行榜,分别是文化分类下的“历史”,“哲学”等几个标签,当然也可以继续增加其他访问链接地址。

但是这个链接地址需要进行预处理,也就是如下图勾画的地方

我们先找到按评分排行的书籍排行榜第二页(因为第一页一般看不出规律)。如下图

然后再到第三页,可以看到start=后面的数字在不断变化,其他都没有变化。

上述写成start={start_rank}是因为字符串的format()方法可以填充该值。

其中book_comments_url也是用相似的方法找到规律后进行的预处理。

2.5 访问书籍排行榜

  def start_requests(self):for url in self.rank_url:for page in range(0, 30):start_rank = page * 20yield Request(url.format(start_rank=start_rank), headers=self.headers,callback=self.parse_to_books)

其中Request方法表示使用headers去访问url,返回的信息用callback中的方法进行处理。

2.6 对书籍排行榜的信息进行处理——xpath方法

def parse_to_books(self, response):# 从html信息中可以看到每本书籍的基本信息都在单独的subject-item,所以先找到所有的subject-itemresults = response.xpath('//li[@class="subject-item"]')# 然后遍历每个subject-item,这里用的results保存的所有subject-itemfor result in results:book_href = result.xpath('./div[@class="info"]/h2/a/@href')book_name = result.xpath('normalize-space(./div[@class="info"]/h2/a/@title)')book_pub = result.xpath('normalize-space(./div[@class="info"]/div[@class="pub"]/text())')book_score = result.xpath('./div[@class="info"]/div/span[@class="rating_nums"]/text()')book_population = result.xpath('normalize-space(./div[@class="info"]/div/span[@class="pl"]/text())')# 用创建BookItem()对象,用其保存书籍的基本信息item_book = BookItem()item_book['book_name'] = book_name.extract()item_book['book_href'] = book_href.extract()print(book_href.extract())# 这里获取book_id,用于访问书籍的评论列表book_id = str(item_book['book_href']).split('/')[-2]print(book_id)item_book['book_pub'] = book_pub.extract()item_book['book_score'] = book_score.extract()item_book['book_population'] = book_population.extract()# 然后遍历该书籍的评论列表前10页,在不登录的情况下,只能访问前10页内容。for page in range(0, 10):# 访问书籍评论列表链接,对返回的页面信息用parse_to_reader处理,meta表示传给parse_to_reader会用到的一些数据,是一个字典,可以根据需要继续添加一些数据。yield Request(self.book_comments_url.format(book_id=book_id, start_comments=page * 20),headers=self.headers,callback=self.parse_to_reader, meta={'book_href': book_href.extract()})yield item_book

2.6 和2.8节会用到BookItem()和ReaderItem_culture(),这几个数据结构在2.9中展示。

2.7 对书籍评论列表页面信息进行处理

这里获取了读者的主页链接、读者的评论,还有传入的meta,也就是书籍的链接,并将上述信息传入到parse_to_reader_address。

def parse_to_reader(self, response):results = response.xpath('//li[@class="comment-item"]')for result in results:reader_href = result.xpath('./div[@class="avatar"]/a/@href').extract()reader_comment = result.xpath('./div[@class="comment"]/p[@class="comment-content"]/span[''@class="short"]/text()').extract()book_href = response.meta['book_href']yield Request(str(reader_href).strip("['").strip("']"), headers=self.headers,callback=self.parse_to_reader_address,meta={'book_href': book_href, 'reader_href': reader_href,'reader_comment': reader_comment})

其基本原理和2.6节一样。这里就不一一赘述了。

2.8 对读者主页信息进行处理

这里获取了读者的地址信息,其基本原理和上述一样,并将信息传入ReaderItem_culture()对象。

def parse_to_reader_address(self, response):print("获取用户地址")book_href = str(response.meta['book_href']).strip("['").strip("']")reader_href = str(response.meta['reader_href']).strip("['").strip("']")reader_comment = str(response.meta['reader_comment'])reader_address_raw = response.xpath('normalize-space(//div[@class="basic-info"]/div[@class="user-info"]/a/text())').extract()reader_address = str(reader_address_raw).strip("['").strip("']")if reader_address.strip() == '':print("地址为空")returnitem_reader = ReaderItem_culture()item_reader['book_href'] = book_hrefitem_reader['reader_href'] = reader_hrefitem_reader['reader_comment'] = reader_commentitem_reader['reader_address'] = reader_addressyield item_reader

2.9 以上用到的Item对象

Item对象在Items.py中申明

import scrapy
class BookItem(scrapy.Item):collection = 'douban_books_culture'book_name = scrapy.Field()book_href = scrapy.Field()book_pub = scrapy.Field()book_score = scrapy.Field()book_population = scrapy.Field()class ReaderItem_culture(scrapy.Item):collection = 'douban_readers_culture'book_href = scrapy.Field()reader_href = scrapy.Field()reader_comment = scrapy.Field()reader_address = scrapy.Field()

其中collection表示的是MongoDB的集合名(类似于MySQL中的表名)。

2.10 小结

以上做了这几件事:

1.对豆瓣的书籍基本信息做了提取,并传入到了BookItem()对象。

2.对读者评论信息、主页链接、地址进行了提取,并传入到了ReaderItem_culture对象。

接下来需要将上述提取的信息存入到MongoDB中。

3.存入数据

存入数据的代码在pipeline.py中书写。

import pymongo
import loggingclass MongoPipeline(object):def __init__(self, mongo_uri, mongo_db):self.mongo_uri = mongo_uriself.mongo_db = mongo_db@classmethod# 这一步是从settings配置文件里面获取MONGO_URI、MONGO_DB两个自己设置的常量def from_crawler(cls, crawler):return cls(mongo_uri=crawler.settings.get('MONGO_URI'),mongo_db=crawler.settings.get('MONGO_DB'))# 这一步是连接MongoDB数据库def open_spider(self, spider):self.client = pymongo.MongoClient(self.mongo_uri)self.db = self.client[self.mongo_db]def process_item(self, item, spider):result = self.db[item.collection].find(item)logging.debug("*"*50)if result.count() == 0:logging.debug("### 无重复、插入数据 ###")self.db[item.collection].insert(dict(item))else:logging.debug("### 有重复、没有插入 ###")logging.debug("*"*50)return itemdef close_spider(self, spider):self.client.close()

4.反爬虫

豆瓣的反爬虫机制很简单,就是看你的访问频率,因此我们仅需要做一个随机延迟访问就可以绕过他的反爬虫机制。

随机延迟在middleware.py中书写。

import logging
import random
import timeclass RandomDelayMiddleware(object):def __init__(self, delay):self.delay = delay@classmethoddef from_crawler(cls, crawler):delay = crawler.spider.settings.get("RANDOM_DELAY", 10)if not isinstance(delay, int):raise ValueError("RANDOM_DELAY need a int")return cls(delay)def process_request(self, request, spider):delay = random.randint(1, self.delay)logging.debug("### random delay: %s s ###" % delay)time.sleep(delay)

5.其他设置

需要修改settings.py文件

还有添加数据库的用户名和密码以及随机延迟上限。

最后修改pipeline.py中的类的优先级以及middleware.py中类的优先级。数字越大,优先级越高。由于我们上述两个文件都分别只有一个类,所以下面配置的意思是先执行RandomDelayMiddleware,再执行MongoPipeline。

6.一些帮助理解的东西

6.1 Scrapy的编码流程

  1. 先写douban_book.py。这里是进行网页页面信息处理的,包括访问、信息提取等。

  2. 再写items.py,如果douban_book.py中需要用到item,就在这里写。

  3. 接着在middlewares.py中写访问延迟。

  4. 然后再pipeline.py中写对item的存储。

  5. 最后在settings.py中配置,包括关闭ROBOTSTXT_OBEY,一些上述文件用到的常量以及优先级设置。

6.2 Scrapy工作流程

这部分仅是个人理解,各取所需。

其实Scrapy项目的执行过程不仅限于我们的项目之下的文件,还有在Scrapy包中的文件。Scrapy项目由以下几个部分组成:Engine(引擎)、Item(项目)、Scheduler(调度器)、Downloader(下载器)、Spiders(蜘蛛)、Item Pipeline(项目管道)、Downloader Middlewares(下载器中间件)、Spider Middleware(蜘蛛中间件)。

其中

  • Item就是items.py中的东西
  • Spiders就是douban_book.py中的东西
  • Downloader Middlewares一部分在Scrapy包中,一部分就是middlewares.py中的东西
  • Item Pipeline就是pipelines.py中的东西。

其工作方式简单点理解就是如下:

  1. Engine从Spider,也就是douban_book.py开始执行,
  2. 然后Engine从Spider中获取了URL,然后将这些URL放入到了Scheduler调度器,通过Request方法调度。应该类似于操作系统里面的调度。
  3. 接着由调度器传URL给Engine,Engine让Downloader Middlewares处理后发送给Downloader进行下载,也就是页面信息等的下载,Downloader会生成该页面信息的Response,然后将Response通过Downloader Middlewares处理后返回给Spider。
  4. 然后Spider处理Response,提取Item,或者新的Request给Engine。
  5. 最后Engine将返回的Item给Item Pipeline,新的Request给Scheduler。
  6. 重复2-6。

Engine就相当于中介,负责Scheduler、Spider、Downloader、Item Pipeline的联系,然后Engine和Downloader联系过程中需要用到Downloader Middlewares进行处理。

爬虫-豆瓣书籍排行榜及用户信息-2021.7.23-使用Scrapy框架-用MongoDB存储数据相关推荐

  1. Python|并发编程|爬虫|单线程|多线程|异步I/O|360图片|Selenium及JavaScript|Scrapy框架|BOM 和 DOM 操作简介|语言基础50课:学习(12)

    文章目录 系列目录 原项目地址 第37课:并发编程在爬虫中的应用 单线程版本 多线程版本 异步I/O版本 总结 第38课:抓取网页动态内容 Selenium 介绍 使用Selenium 加载页面 查找 ...

  2. Python爬虫爬取知乎用户信息+寻找潜在客户

    [Python应用]寻找社交网络中的目标用户 日后的更新:由于是很久以前的课程设计项目,完整的源码已经不见了,关键的网页数据获取和解析的部分代码我在文章中已经贴出来了,但写的也不够好,如果想参考爬取知 ...

  3. python爬虫scrapy框架爬取网页数据_Scrapy-Python

    scrapy Scrapy:Python的爬虫框架 实例Demo 抓取:汽车之家.瓜子.链家 等数据信息 版本+环境库 Python2.7 + Scrapy1.12 初窥Scrapy Scrapy是一 ...

  4. python3爬虫----人人贷散标用户信息爬取

    前提 本文基于此篇博文的实现思路以及给出的代码.不得不说,此博主心真的细,这个数据隐藏点都找到了,从而使得此爬虫的实现简单许多. 但我在使用博主代码时,发现人人贷网站有些许改变,于是对应代码我也相应做 ...

  5. 搭建nuxtjs程序 —— 用户信息 or token怎么不丢失

    框架背景:开发框架采用vue,需要更好的SEO,更快的内容到达时间,从浏览器看不到对服务器的请求接口,选用开箱即用的nuxtjs. 问题背景:1. 前后分离,需前端存储token及登录后的用户信息: ...

  6. python爬取豆瓣书籍_Python利用lxml模块爬取豆瓣读书排行榜的方法与分析

    前言 上次使用了BeautifulSoup库爬取电影排行榜,爬取相对来说有点麻烦,爬取的速度也较慢.本次使用的lxml库,我个人是最喜欢的,爬取的语法很简单,爬取速度也快. 本次爬取的豆瓣书籍排行榜的 ...

  7. python爬虫模块排名_Python爬虫使用lxml模块爬取豆瓣读书排行榜并分析

    上次使用了beautifulsoup库爬取电影排行榜,爬取相对来说有点麻烦,爬取的速度也较慢.本次使用的lxml库,我个人是最喜欢的,爬取的语法很简单,爬取速度也快. 本次爬取的豆瓣书籍排行榜的首页地 ...

  8. 爬虫项目实战一:基于Scrapy+MongDB爬取并存储糗事百科用户信息

    爬虫项目实战一:基于Scrapy+MongDB爬取并存储糗事百科用户信息 一.前言 二.项目目标 三.项目的环境配置 四.项目实现 1. 创建QSBK项目 2. 实现Spider 1. 实现一页网页上 ...

  9. 【微信小程序】获取用户信息

    文章目录 获取用户信息 组件open-data button组件中的open-type 接口getUserProfile 查看授权结果 获取用户信息 组件open-data 组件 open-data用 ...

最新文章

  1. 高校复试计算机英语文献翻译,专业文献英语翻译复试.pdf
  2. 借双慧眼识别钓鱼欺诈网站
  3. 个人所得税的申报方式有两种,分别有什么区别?该怎么选?
  4. c语言min函数_C语言探索之旅 | 第一部分第十课:第一个C语言小游戏
  5. python numpy中bool变量转为1或0
  6. 【iOS】Web Color 的 Swift 实现
  7. 手机电脑同屏_把手游变成端游的同屏神器,就是这款Onebit“X9”了!
  8. Kite的学习历程SpringCloud之Seata安装
  9. 设计模式之责任链模式(Java实现)
  10. ntag213和215有什么区别_NTAG213、NTAG215和NTAG216NFC标签
  11. 微信小程序base64转为二维码、条形码图片
  12. osgearth加载倾斜摄影数据
  13. android star法则简历,优秀简历的STAR原则
  14. css 剪辑图片_css剪裁GIF背景图片动画特效
  15. 蓝桥杯(纯C)比赛--菜鸟级
  16. 《LaneAF:Robust Multi-Lane Detection with Affinity Fields》论文笔记
  17. 解决TensorFlow“Your CPU supports instructions TensorFlow binary was not compiled to use : AVX2 FMA”
  18. 2011年最新企业offer
  19. 怎样才能批量查询网站的谷歌PR权重?把手教你批量查询网站谷歌PR权重值
  20. python求向量长度_得到向量的大小(x,y)

热门文章

  1. 台式电脑Window系统使用耳机的喇叭和麦克风方法
  2. 【小米集团】2019校招在线考试-算法试卷编程题
  3. 需求工程中的面谈和原型
  4. RabbitMq(五) -- 死信队列和延迟队列
  5. 利用 python numpy +matplotlib 绘制股票k线图
  6. 用C++制作一款电话簿
  7. android 自定义view,字母排序(仿微信好友列表)
  8. 如何将macbook触摸板和外接鼠标的滚轮设置相反方向
  9. python中大于0怎么表示_python怎么筛选列表中大于0的数据?
  10. python英文参考文献格式_英文参考文献标准格式