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 相关文章推荐
python类中super()和__init__()的区别
Oct 18 Python
Python开发中爬虫使用代理proxy抓取网页的方法示例
Sep 26 Python
Python数据分析之双色球中蓝红球分析统计示例
Feb 03 Python
浅谈Python中重载isinstance继承关系的问题
May 04 Python
python 基本数据类型占用内存空间大小的实例
Jun 12 Python
python判断完全平方数的方法
Nov 13 Python
python字符串分割及字符串的一些常规方法
Jul 24 Python
tensorflow 实现打印pb模型的所有节点
Jan 23 Python
python去除删除数据中\u0000\u0001等unicode字符串的代码
Mar 06 Python
利用python查看数组中的所有元素是否相同
Jan 08 Python
Python使用Turtle模块绘制国旗的方法示例
Feb 28 Python
详解PyTorch模型保存与加载
Apr 28 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
测试php函数的方法
2013/11/13 PHP
注意!PHP 7中不要做的10件事
2016/09/18 PHP
Mac下php 5升级到php 7的步骤详解
2017/04/26 PHP
如何修改Laravel中url()函数生成URL的根地址
2017/08/11 PHP
PHP排序算法之直接插入排序(Straight Insertion Sort)实例分析
2018/04/20 PHP
PHP实现断点续传乱序合并文件的方法
2018/09/06 PHP
Cookie 注入是怎样产生的
2009/04/08 Javascript
JavaScript Accessor实现说明
2010/12/06 Javascript
javascript中encodeURI和decodeURI方法使用介绍
2013/05/06 Javascript
通过js简单实现将一个文本内容转译成加密文本
2013/10/22 Javascript
浅谈JavaScript函数参数的可修改性问题
2013/12/05 Javascript
jQuery中的jQuery()方法用法分析
2014/12/27 Javascript
JQuery中$.each 和$(selector).each()的区别详解
2015/03/13 Javascript
整理Javascript事件响应学习笔记
2015/12/02 Javascript
JavaScript的变量声明提升问题浅析(Hoisting)
2016/11/30 Javascript
JavaScript hasOwnProperty() 函数实例详解
2017/08/04 Javascript
Vue 中如何正确引入第三方模块的方法步骤
2019/05/05 Javascript
jquery实现下载图片功能
2019/07/18 jQuery
extjs图表绘制之条形图实现方法分析
2020/03/06 Javascript
vue中使用router全局守卫实现页面拦截的示例
2020/10/23 Javascript
Python 实现在文件中的每一行添加一个逗号
2018/04/29 Python
Python爬虫实现抓取京东店铺信息及下载图片功能示例
2018/08/07 Python
Python机器学习之scikit-learn库中KNN算法的封装与使用方法
2018/12/14 Python
python实现银行管理系统
2019/10/25 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
html5 button autofocus 属性介绍及应用
2013/01/04 HTML / CSS
孤独星球出版物:Lonely Planet Publications
2018/03/17 全球购物
Fox Racing英国官网:越野摩托车和山地自行车服装
2020/02/26 全球购物
大学本科毕业生的自我鉴定范文
2013/11/19 职场文书
民主评议党员总结
2014/10/20 职场文书
2014年团支书工作总结
2014/11/14 职场文书
初中生300字旷课检讨书
2014/11/19 职场文书
公务员个人年终总结
2015/02/12 职场文书
债务追讨律师函
2015/06/24 职场文书
关于车尾的标语大全
2015/08/11 职场文书
.Net Core导入千万级数据至Mysql的步骤
2021/05/24 MySQL