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抓取网页图片示例(python爬虫)
Apr 27 Python
在Python中使用全局日志时需要注意的问题
May 06 Python
Python使用Windows API创建窗口示例【基于win32gui模块】
May 09 Python
pandas筛选某列出现编码错误的解决方法
Nov 07 Python
Python参数类型以及常见的坑详解
Jul 08 Python
python 根据字典的键值进行排序的方法
Jul 24 Python
python利用re,bs4,requests模块获取股票数据
Jul 29 Python
解决python 文本过滤和清理问题
Aug 28 Python
tensorflow 获取所有variable或tensor的name示例
Jan 04 Python
Python多线程的退出控制实现
Aug 10 Python
Python用Jira库来操作Jira
Dec 28 Python
浅谈Python项目的服务器部署
Apr 25 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获取数组中单列值的方法
2017/06/10 PHP
MooTools 1.2介绍
2009/09/14 Javascript
基于JavaScript 类的使用详解
2013/05/07 Javascript
jQuery Ajax调用WCF服务详细教程
2015/03/31 Javascript
jQuery $.each遍历对象、数组用法实例
2015/04/16 Javascript
谈谈Jquery中的children find 的区别有哪些
2015/10/19 Javascript
jquery 实现回车登录详解及实例代码
2016/10/23 Javascript
关于webuploader插件使用过程遇到的小问题
2016/11/07 Javascript
js窗口震动小程序分享
2016/11/28 Javascript
RequireJs的使用详解
2017/02/19 Javascript
vue实现商城购物车功能
2017/11/27 Javascript
浅谈super-vuex使用体验
2018/06/25 Javascript
Vue实现动态添加或者删除对象和对象数组的操作方法
2018/09/21 Javascript
在vue中实现给每个页面顶部设置title
2020/07/29 Javascript
详解vue-cli项目在IE浏览器打开报错解决方法
2020/12/10 Vue.js
python用装饰器自动注册Tornado路由详解
2017/02/14 Python
Python文件操作基本流程代码实例
2017/12/11 Python
Tornado Web Server框架编写简易Python服务器
2018/07/28 Python
基于Python安装pyecharts所遇的问题及解决方法
2019/08/12 Python
Python3离线安装Requests模块问题
2019/10/13 Python
keras实现多种分类网络的方式
2020/06/11 Python
Biblibili视频投稿接口分析并以Python实现自动投稿功能
2021/02/05 Python
德国骆驼商店:ActiveFashionWorld
2017/11/18 全球购物
NFL墨西哥官方商店:Tienda NFL
2017/11/28 全球购物
大学自荐信
2013/12/12 职场文书
幼儿园秋游活动方案
2014/01/21 职场文书
卫生标语大全
2014/06/21 职场文书
小学安全汇报材料
2014/08/14 职场文书
个人工作能力自我评价
2015/03/05 职场文书
拯救大兵瑞恩观后感
2015/06/09 职场文书
公务员岗前培训心得体会
2016/01/08 职场文书
创业计划书之宠物店
2019/09/19 职场文书
react国际化react-intl的使用
2021/05/06 Javascript
MySQL 覆盖索引的优点
2021/05/19 MySQL
浅谈Java父子类加载顺序
2021/08/04 Java/Android
德劲DE1105机评
2022/04/05 无线电