​开始接触爬虫的时候还是初学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 = ''

scrapy增量爬取的更多相关文章

  1. scrapy过滤重复数据和增量爬取

    原文链接 前言 这篇笔记基于上上篇笔记的---<scrapy电影天堂实战(二)创建爬虫项目>,而这篇又涉及redis,所以又先熟悉了下redis,记录了下<redis基础笔记> ...

  2. 爬虫07 /scrapy图片爬取、中间件、selenium在scrapy中的应用、CrawlSpider、分布式、增量式

    爬虫07 /scrapy图片爬取.中间件.selenium在scrapy中的应用.CrawlSpider.分布式.增量式 目录 爬虫07 /scrapy图片爬取.中间件.selenium在scrapy ...

  3. 使用scrapy实现去重,使用Redis实现增量爬取

    面试场景: 要求对正在爬取的内容与mysql数据库中的数据进行比较去重 解决方式: 通过Redis来作为中间件,通过url来确保爬过的数据不会再爬,做到增量爬取. Redis数据库其实就是一个中间件, ...

  4. webmagic 增量爬取

    webmagic  是一个很好并且很简单的爬虫框架,其教程网址:http://my.oschina.net/flashsword/blog/180623 webmagic参考了scrapy的模块划分, ...

  5. 简单的scrapy实战:爬取腾讯招聘北京地区的相关招聘信息

    简单的scrapy实战:爬取腾讯招聘北京地区的相关招聘信息 简单的scrapy实战:爬取腾讯招聘北京地区的相关招聘信息 系统环境:Fedora22(昨天已安装scrapy环境) 爬取的开始URL:ht ...

  6. 使用scrapy框架爬取自己的博文(2)

    之前写了一篇用scrapy框架爬取自己博文的博客,后来发现对于中文的处理一直有问题- - 显示的时候 [u'python\u4e0b\u722c\u67d0\u4e2a\u7f51\u9875\u76 ...

  7. 如何提高scrapy的爬取效率

    提高scrapy的爬取效率 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增加.在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置 ...

  8. scrapy框架爬取笔趣阁完整版

    继续上一篇,这一次的爬取了小说内容 pipelines.py import csv class ScrapytestPipeline(object): # 爬虫文件中提取数据的方法每yield一次it ...

  9. scrapy框架爬取笔趣阁

    笔趣阁是很好爬的网站了,这里简单爬取了全部小说链接和每本的全部章节链接,还想爬取章节内容在biquge.py里在加一个爬取循环,在pipelines.py添加保存函数即可 1 创建一个scrapy项目 ...

随机推荐

  1. SQL-W3School-高级:SQL JOIN

    ylbtech-SQL-W3School-高级:SQL JOIN 1.返回顶部 1. SQL join 用于根据两个或多个表中的列之间的关系,从这些表中查询数据. Join 和 Key 有时为了得到完 ...

  2. kotlin数据解构

    fun main(arg: Array<String>) { val person = person("tom") var (name) = person//解构 pr ...

  3. kubernetes监控(12)

    一.Weave Scope 1. weave scope 容器地图 创建 Kubernetes 集群并部署容器化应用只是第一步.一旦集群运行起来,我们需要确保一起正常,所有必要组件就位并各司其职,有足 ...

  4. SaaS领域如何分析收入增长?

    SaaS领域如何分析收入增长? 今天我们试着将其模式运用到收入增长上进行分析.这对常规收入的计算会极有帮助,例如企业级应用软件(SaaS)或消费者订阅业务. 列举某公司通过月度订阅获得营收为例,为了更 ...

  5. 深入理解 iptables 和 netfilter 架构

    [译] 深入理解 iptables 和 netfilter 架构 Published at 2019-02-18 | Last Update 译者序 本文翻译自 2015 年的一篇英文博客 A Dee ...

  6. Jenkins创建镜像后无法推送到harbor的问题

    https://blog.csdn.net/mydeman/article/details/79042848 1.先切换到root账号,用root登录harbor,就可以push $ sudo pas ...

  7. jprofile 远程监控linux上的jvm

    环境 客户端:win7+jprofiler_windows-x64_10_0_4.exe linux服务器:tomcat7+jdk1.7+jprofiler_linux_10_0_4.sh 一.客户端 ...

  8. nginx 解决session一致性

    session 粘滞性每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题. upstream backserver {ip_hash;server ...

  9. laravel 自带消息notification通知

    原文地址:https://blog.csdn.net/zhangxh1013/article/details/53130490

  10. C语言tips_2 关于scanf 读取规则小结以及与getchar 的区别

    第一点:scanf默认回车和空格是输入不同组之间的间隔和结束符号. 也就是说他不会读取 空格 和 换行符.而是把他们当作一个 数据被读取完成的标志!他的停止标志则为,当%d之类的数据输入结束之后,自动 ...