Python scrapy增量爬取实例及实现过程解析


Posted in Python onDecember 24, 2019

这篇文章主要介绍了Python scrapy增量爬取实例及实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

开始接触爬虫的时候还是初学Python的那会,用的还是request、bs4、pandas,再后面接触scrapy做个一两个爬虫,觉得还是框架好,可惜都没有记录都忘记了,现在做推荐系统需要爬取一定的文章,所以又把scrapy捡起来。趁着这次机会做一个记录。

目录如下:

  • 环境
  • 本地窗口调试命令
  • 工程目录
  • xpath选择器
  • 一个简单的增量爬虫示例
  • 配置介绍

环境

​自己的环境下安装scrapy肯定用anaconda(再次强调anaconda的优越性

本地窗口调试与运行

开发的时候可以利用scrapy自带的调试功能进行模拟请求,这样request、response都会与后面代码保持一样。

# 测试请求某网站
scrapy shell URL
# 设置请求头
scrapy shell -s USER_AGENT="Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0" URL

# 指定爬虫内容输出文件格式(json、csv等
scrapy crawl SPIDER_NAME -o FILE_NAME.csv

# 创建爬虫工程
scrapy startproject articles # 在当前目录创建一个scrapy工程

新工程结构介绍

# spiders文件下存放所有爬虫,item.py格式化数据输出
# middlewares.py 设置请求细节(请求头之类的),pipelines.py为数据输出的管道,每一个封装好的item都会经过这里
# settings.py 对工程进行全局设置(存放配置
├── articles
│  ├── articles
│  │  ├── __init__.py
│  │  ├── items.py
│  │  ├── middlewares.py
│  │  ├── pipelines.py
│  │  ├── settings.py
│  │  └── spiders
│  │    ├── healthy_living.py
│  │    ├── __init__.py
│  │    └── people_health.py
│  └── scrapy.cfg
├── README.en.md
└── README.md

页面解析神器——Xpath选择器

scrapy自带xpath选择器,很方便,简单介绍一些常用的

# 全站爬取神器--LinkExtractor,可以自动获取该标签下的所有url跟text(因为网站结构大都一个套路
from scrapy.linkextractors import LinkExtractor
le = LinkExtractor(restrict_xpaths="//ul[@class='nav2_UL_1 clearFix']")# 返回一个迭代器,通过循环(for i in le),可获取url(i.url) (i.text)

# 获取属性class为所有aa的div标签内容中的内容
response.xpath("//div[@class='aa']/text()").extract()    # '//'代表获取所有,'/'代表获取第一个,类似的可以找属性为ul的其它标签

# 获取内容包含“下一页”的所有a标签中包含的链接(提取下一页链接神器
response.xpath("//a[contains(text(),'下一页')]/@href").extract()

一个简单的增量爬取示例

这里增量爬取的思想很简单:目标网站的数据都是按照时间排列的,所以在对某个连接进行request之前,先查询数据库中有没有这条数据,如果有,就停止爬虫,如果没有发起请求

class HealthyLiving(scrapy.Spider):
  # 一定要一个全局唯一的爬虫名称,命令行启动的时候需要指定该名称
  name = "healthy_living"
  # 指定爬虫入口,scrapy支持多入口,所以一定是lis形式
  start_urls = ['http://www.jkb.com.cn/healthyLiving/']

  '''
  抓取大类标签入口
  '''
  def parse(self, response):
    le = LinkExtractor(restrict_xpaths="//ul[@class='nav2_UL_1 clearFix']")
    for link in le.extract_links(response)[1:-1]:
      tag = link.text
      # 将这一级提取到的信息,通过请求头传递给下一级(这里是为了给数据打标签
      meta = {"tag": tag}
      # 依次解析每一个链接,并传递到下一级进行继续爬取
      yield scrapy.Request(link.url, callback=self.parse_articles, meta=meta)

  '''
  抓取页面内的文章链接及下一页链接
  '''
  def parse_articles(self, response):
    # 接收上一级传递的信息
    meta = response.meta
    article_links = response.xpath("//div[@class='txt']/h4/a/@href").extract()
    for link in article_links:
      res = self.collection.find_one({"article_url": link}, {"article_url": 1})
      full_meta = dict(meta)
      # 将文章链接传入下一级
      full_meta.update({"article_url": link})
      if res is None:
        yield scrapy.Request(link, callback=self.parse_article, meta=full_meta)
      else:
        return
    next_page = response.xpath("//div[@class='page']//a[contains(text(),'»')]/@href").extract()[0]
    if next_page:
      yield scrapy.Request(next_page, callback=self.parse_articles, meta=meta)

# 最后解析页面,并输出
  def parse_article(self, response):
   # 从item.py中导入数据封装格式
    article_item = ArticlesItem()
    meta = response.meta
    # 利用xpath提取页面信息并封装成item
    try:
      article_item["tag"] = ""
      # ... 省略
    finally:
      yield article_item

工程配置介绍

设置请求头、配置数据库

# 设置请求头,在middlewares.py中设定,在settings.py中启用
class RandomUA(object):
  user_agents = [
      "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit"
      "/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36",
      "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11",
      "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit"
      "/534.16 (KHTML, like Gecko) Chrome/10.0.648.133 Safari/534.16"
    ]

  def process_request(self, request, spider):
    request.headers["User-Agent"] = random.choice(self.user_agents)


# 设置数据入库处理,在pipeline.py进行配置,在settings.py进行启用
class MongoPipeline(object):
  def __init__(self, mongo_uri, mongo_db):
    self.mongo_uri = mongo_uri
    self.mongo_db = mongo_db

  @classmethod
  def from_crawler(cls, crawler):
    return cls(
      mongo_uri=crawler.settings.get('MONGO_URI'),
      mongo_db=crawler.settings.get('MONGO_DB')
    )

  def open_spider(self, spider):
    print("开始爬取", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    self.client = pymongo.MongoClient(self.mongo_uri)
    self.db = self.client[self.mongo_db]

  def process_item(self, item, spider):
    data = self.db[item.collection].find_one({"title": item["title"], "date": item["date"]})

    if data is None:
      self.db[item.collection].insert(dict(item))
    # else:
    #   self.close_spider(self, spider)
    return item

  def close_spider(self, spider):
    print("爬取结束", datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    self.client.close()
# 在settings.py启动:请求头的修改,数据库的配置
DOWNLOADER_MIDDLEWARES = {
  # 'articles.middlewares.ArticlesDownloaderMiddleware': 543,
  'articles.middlewares.RandomUA': 543,# 543代表优先级,数字越低优先级越高
}

ITEM_PIPELINES = {
  'articles.pipelines.MongoPipeline': 300,
}

# 一些其它配置
ROBOTSTXT_OBEY = True # 是否遵守网站的robot协议
FEED_EXPORT_ENCODING = 'utf-8' # 指定数据输出的编码格式
## 数据库配置
MONGO_URI = ''
MONGO_DB = ''
MONGO_PORT = 27017
MONGO_COLLECTION = ''

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
安装ElasticSearch搜索工具并配置Python驱动的方法
Dec 22 Python
python爬虫实战之最简单的网页爬虫教程
Aug 13 Python
Python 通配符删除文件的实例
Apr 24 Python
Django使用paginator插件实现翻页功能的实例
Oct 24 Python
python仿抖音表白神器
Apr 08 Python
python元组和字典的内建函数实例详解
Oct 22 Python
Python爬取腾讯视频评论的思路详解
Dec 19 Python
Python流程控制常用工具详解
Feb 24 Python
Python通过4种方式实现进程数据通信
Mar 12 Python
快速解决Django关闭Debug模式无法加载media图片与static静态文件
Apr 07 Python
解决jupyter notebook图片显示模糊和保存清晰图片的操作
Apr 24 Python
asyncio异步编程之Task对象详解
Mar 13 Python
Python 元组拆包示例(Tuple Unpacking)
Dec 24 #Python
Python 余弦相似度与皮尔逊相关系数 计算实例
Dec 23 #Python
Python编译成.so文件进行加密后调用的实现
Dec 23 #Python
Cython编译python为so 代码加密示例
Dec 23 #Python
Python编译为二进制so可执行文件实例
Dec 23 #Python
Python+opencv+pyaudio实现带声音屏幕录制
Dec 23 #Python
python 实现屏幕录制示例
Dec 23 #Python
You might like
pdo中使用参数化查询sql
2011/08/11 PHP
php函数array_merge用法一例(合并同类数组)
2013/02/03 PHP
php实现模拟登陆方正教务系统抓取课表
2015/05/19 PHP
jQuery级联操作绑定事件实例
2014/09/02 Javascript
JavaScript实现获取dom中class的方法
2015/02/09 Javascript
javascript中利用柯里化函数实现bind方法【推荐】
2016/04/29 Javascript
深入理解事件冒泡(Bubble)和事件捕捉(capture)
2016/05/28 Javascript
bootstrap输入框组使用方法
2017/02/07 Javascript
ECMAScript6--解构
2017/03/30 Javascript
详解有关easyUI的拖动操作中droppable,draggable用法例子
2017/06/03 Javascript
JS+jQuery实现注册信息的验证功能
2017/09/26 jQuery
jQuery实现每隔一段时间自动更换样式的方法分析
2018/05/03 jQuery
vue项目引入Iconfont图标库的教程图解
2018/10/24 Javascript
优雅地使用loading(推荐)
2019/04/20 Javascript
vue-test-utils初使用详解
2019/05/23 Javascript
使用express来代理服务的方法
2019/06/21 Javascript
浅谈vue 锚点指令v-anchor的使用
2019/11/13 Javascript
vue element自定义表单验证请求后端接口验证
2019/12/11 Javascript
Vue-CLI 3 scp2自动部署项目至服务器的方法
2020/07/24 Javascript
vue addRoutes路由动态加载操作
2020/08/04 Javascript
微信小程序实现点击导航标签滚动定位到对应位置
2020/11/19 Javascript
对Python中type打开文件的方式介绍
2018/04/28 Python
Python进阶之全面解读高级特性之切片
2019/02/19 Python
python3 selenium自动化 frame表单嵌套的切换方法
2019/08/23 Python
Python格式化输出--%s,%d,%f的代码解析
2020/04/29 Python
HTML5播放实现rtmp流直播
2020/06/16 HTML / CSS
Ariat官网:美国马靴和服装品牌
2019/12/16 全球购物
安全教育实施方案
2014/03/02 职场文书
《三个小伙伴》教学反思
2014/04/11 职场文书
大学生职业生涯规划大赛作品(精品)
2014/09/17 职场文书
2014幼儿园保育员工作总结
2014/11/10 职场文书
党员考试作弊检讨书1000字
2015/02/16 职场文书
2016新年问候语大全
2015/11/11 职场文书
2016年党员公开承诺书范文
2016/03/24 职场文书
解决Go gorm踩过的坑
2021/04/30 Golang
pytorch中F.avg_pool1d()和F.avg_pool2d()的使用操作
2021/05/22 Python