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求解平方根的方法
Mar 11 Python
Python标准库之Sys模块使用详解
May 23 Python
使用Python对MySQL数据操作
Apr 06 Python
python写一个md5解密器示例
Feb 23 Python
PyQt5每天必学之QSplitter实现窗口分隔
Apr 19 Python
python实现超简单的视频对象提取功能
Jun 04 Python
Python中shapefile转换geojson的示例
Jan 03 Python
python使用Plotly绘图工具绘制散点图、线形图
Apr 02 Python
JupyterNotebook 输出窗口的显示效果调整方法
Apr 13 Python
解决Django Haystack全文检索为空的问题
May 19 Python
python中判断数字是否为质数的实例讲解
Dec 06 Python
Python控制台输出俄罗斯方块移动和旋转功能
Apr 18 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设计模式 FlyWeight (享元模式)
2011/06/26 PHP
CI框架开发新浪微博登录接口源码完整版
2014/05/28 PHP
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
PHP连接MySQL数据库三种实现方法
2020/12/10 PHP
JavaScript中Math对象使用说明
2008/01/16 Javascript
JavaScript prototype属性使用说明
2010/05/13 Javascript
按钮JS复制文本框和表格的代码
2011/04/01 Javascript
php+js实现倒计时功能
2014/06/02 Javascript
jquery 新建的元素事件绑定问题解决方案
2014/06/12 Javascript
JavaScript搜索字符串并将搜索结果返回到字符串的方法
2015/04/06 Javascript
Angularjs中controller的三种写法分享
2016/09/21 Javascript
javascript 实现文本使用省略号替代(超出固定高度的情况)
2017/02/21 Javascript
Angular.js中定时器循环的3种方法总结
2017/04/27 Javascript
angular4中关于表单的校验示例
2017/10/16 Javascript
基于Bootstrap表单验证功能
2017/11/17 Javascript
基于vue2实现左滑删除功能
2017/11/28 Javascript
vue中各种通信传值方式总结
2019/02/14 Javascript
jQuery分组选择器简单用法示例
2019/04/04 jQuery
layui禁用侧边导航栏点击事件的解决方法
2019/09/25 Javascript
vue 封装 Adminlte3组件的实现
2020/03/18 Javascript
python条件和循环的使用方法
2013/11/01 Python
Python读取csv文件分隔符设置方法
2019/01/14 Python
Django中使用CORS实现跨域请求过程解析
2019/08/05 Python
Python文件操作及内置函数flush原理解析
2020/10/13 Python
python3访问字典里的值实例方法
2020/11/18 Python
记一次python 爬虫爬取深圳租房信息的过程及遇到的问题
2020/11/24 Python
Python Spyder 调出缩进对齐线的操作
2021/02/26 Python
HTML5视频播放插件 video.js介绍
2018/09/29 HTML / CSS
数控专业大学生的自我鉴定
2013/11/13 职场文书
自动化专业个人求职信范文
2013/11/29 职场文书
施工人员岗位职责
2013/12/12 职场文书
公司请假条范文
2014/04/11 职场文书
旅游节目策划方案
2014/05/26 职场文书
小学四年级作文之人物作文
2019/11/06 职场文书
利用ajax+php实现商品价格计算
2021/03/31 PHP
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL