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之玩转字符串(2)更新篇
Sep 28 Python
使用Python的web.py框架实现类似Django的ORM查询的教程
May 02 Python
Python中字符串的格式化方法小结
May 03 Python
Python实现MySQL操作的方法小结【安装,连接,增删改查等】
Jul 12 Python
Python cookbook(数据结构与算法)将序列分解为单独变量的方法
Feb 13 Python
30秒轻松实现TensorFlow物体检测
Mar 14 Python
一些Centos Python 生产环境的部署命令(推荐)
May 07 Python
用于业余项目的8个优秀Python库
Sep 21 Python
Python 微信爬虫完整实例【单线程与多线程】
Jul 06 Python
python GUI库图形界面开发之PyQt5布局控件QGridLayout详细使用方法与实例
Mar 06 Python
使用Python+selenium实现第一个自动化测试脚本
Mar 17 Python
超级实用的8个Python列表技巧
Aug 24 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
150kHz到30Mhz完全冲浪手册
2020/03/20 无线电
php join函数应用
2011/05/04 PHP
PHP中快速生成随机密码的几种方式
2017/04/17 PHP
PHP编程实现的TCP服务端和客户端功能示例
2018/04/13 PHP
Yii2.0框架实现带分页的多条件搜索功能示例
2019/02/20 PHP
PHP使用POP3读取邮箱接收邮件的示例代码
2020/07/08 PHP
jQuery EasyUI API 中文文档 - DataGrid数据表格
2011/11/17 Javascript
js实现翻页后保持checkbox选中状态的实现方法
2012/11/03 Javascript
JavaScript中的Math.atan2()方法使用详解
2015/06/15 Javascript
js仿黑客帝国字母掉落效果代码分享
2020/11/08 Javascript
分享我对JS插件开发的一些感想和心得
2016/02/04 Javascript
JavaScript高级程序设计(第三版)学习笔记1~5章
2016/03/11 Javascript
jQuery操作动态生成的内容的方法
2016/05/28 Javascript
浅析JavaScript中的array数组类型系统
2016/07/18 Javascript
js实现input密码框显示/隐藏功能
2020/09/10 Javascript
JavaScript实现的开关灯泡点击切换特效示例
2019/07/08 Javascript
详解Vue后台管理系统开发日常总结(组件PageHeader)
2019/11/01 Javascript
JavaScript实现捕获鼠标坐标
2020/04/12 Javascript
jQuery+css实现的点击图片放大缩小预览功能示例【图片预览 查看大图】
2020/05/29 jQuery
python实现多线程的方式及多条命令并发执行
2016/06/07 Python
python+pyqt实现12306图片验证效果
2017/10/25 Python
基于python list对象中嵌套元组使用sort时的排序方法
2018/04/18 Python
python使用多进程的实例详解
2018/09/19 Python
开发人员所需要知道的HTML5性能分析面面观
2012/07/05 HTML / CSS
Html5饼图绘制实现统计图的方法
2020/08/05 HTML / CSS
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
英国在线玫瑰专家:InterRose
2019/12/01 全球购物
香港家用健身器材、运动器材及健康美容仪器专门店:FitBoxx
2019/12/05 全球购物
职业规划书如何设计?
2014/01/09 职场文书
关于圣诞节的广播稿
2014/01/26 职场文书
美国探亲签证邀请信
2014/02/05 职场文书
2014年小学校长工作总结
2014/12/08 职场文书
2015年元旦主持词开场白
2014/12/14 职场文书
邀请书模板
2015/02/02 职场文书
2015银行年终工作总结范文
2015/05/26 职场文书
解决vue-router的beforeRouteUpdate不能触发
2022/04/14 Vue.js