上一篇简单了解了scrapy各个模块的功能:Scrapy框架初探 -- Dapianzi卡夫卡

在这篇通过一些实例来深入理解 scrapy 的各个对象以及它们是怎么相互协作的

settings.py 配置文件

#USER_AGENT = 'cats (+http://www.yourdomain.com)'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36' # Obey robots.txt rules 是否乖乖听从robot.txt
#ROBOTSTXT_OBEY = True # Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32 # Configure a delay for requests for the same website (default: 0)
# See http://scrapy.readthedocs.org/en/latest/topics/settings.html#download-delay
# See also autothrottle settings and docs 请求间隔时间。需要看抓取时间需求,IP资源,目标网站反爬虫策略
DOWNLOAD_DELAY = 1
# The download delay setting will honor only one of: 二选一,按ip还是按域名设置请求上限
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
CONCURRENT_REQUESTS_PER_IP = 16 # Disable cookies (enabled by default) 自动处理cookie,需要登录会话
#COOKIES_ENABLED = False
COOKIES_ENABLED = True # Disable Telnet Console (enabled by default)
TELNETCONSOLE_ENABLED = False # Override the default request headers: 默认的http headers
DEFAULT_REQUEST_HEADERS = {
'Connection': 'Keep-Alive',
'Accept': 'text/html, application/xhtml+xml,*/*',
'Accept-Language': 'zh-CN',
'Accept-Encoding': 'gzip, deflate',
}

其实看注释就已经很清楚各个配置项是什么作用了,根据自己的需求,目标网站的反爬虫策略来配置就好了

另外可以任意添加自己自定义的配置项,比如MySQL配置:

# MYSQL CONFIG
MYSQL_HOST = '127.0.0.1'
MYSQL_PORT = 3307
MYSQL_USER = 'root'
MYSQL_PASS = ''
MYSQL_NAME = 'pets'

在项目中需要使用的时候,使用 crawler 对象。在 pipelines.py 中 的例子:

@classmethod
def from_crawler(cls, crawler):
'''static function'''
host = crawler.settings.get('MYSQL_HOST')
...

pipelines.py 管道处理

管道处理,根据字面意思当然是可以定义不同的逻辑,按顺序对 Items 进行处理。

管道顺序

管道的顺序需要在 settings.py 定义

 ITEM_PIPELINES = {
# enable image pipeline
'cats.pipelines.FilterPipeline': 1,
'cats.pipelines.ImgsPipeline': 100,
'cats.pipelines.CatsPipeline': 300,
}

这里定义了3个管道,分别是 过滤去重 -> 下载图片 -> 保存到数据库 。后面的数字代表管道权重

@classmethod[from_crawler] 初始化管道

这个是从官方文档看到的,为了从 settings.py 读取相关配置,调用类方法来初始化 管道处理器。在使用数据库的时候很方便:

db = None
cursor = None def __init__(self, conf):
try:
self.db = pymysql.connect(conf['host'], conf['user'], conf['pass'], conf['name'], port=conf['port'], charset='utf8')
except pymysql.OperationalError as e:
print ("Mysql Operation Error[%d]: %s" % tuple(e))
exit(0)
self.cursor = self.db.cursor() def __del__(self):
self.db.close() @classmethod
def from_crawler(cls, crawler):
'''static function'''
return cls({
'host' : crawler.settings.get('MYSQL_HOST'),
'port' : crawler.settings.get('MYSQL_PORT'),
'name' : crawler.settings.get('MYSQL_NAME'),
'user' : crawler.settings.get('MYSQL_USER'),
'pass' : crawler.settings.get('MYSQL_PASS')
})

process_item() 管道处理方法

这里是对 Item 进行处理的主要方法,数据库落地或者 DropItem() .处理完成记得 return item

sql = "SELECT id FROM cat_imgs WHERE img_hash=%s"
self.cursor.execute(sql, (item['img_hash'], ))
if self.cursor.fetchone():
spider.log('HASH exists.')
raise DropItem("HASH exists.")
else:
return item

ImagesPipeline 图片下载

【官方文档】Downloading and processing files and images

  • 新建一个类继承 ImagesPipeline。因为不是普通的 pipeline,因此__init__(),process_item(),spider_open(),from_crawler() 等方法可能不适用

  • get_media_requests(self, item, info) 下载图片方法第三个参数info存储了spider的信息,可以直接获取spider的属性:

      def get_media_request(self, item, info):
    name = info.spider.name
    ref = info.spider.ref
    return Request(item['img_src'], headers={"Referer": ref})
  • item_completed(self, results, item, info) 图片下载完成后的处理。results参数始终是一个 list, 跟你定义的 Item 字段没有关系

      def item_completed(self, results, item, info):
    
          for ok,x in results:
    if not ok:
    raise DropItem("Item contains no files")
    item['img_src'] = x['path']
    # 我的 item 结构中 只有一个图片资源
    return item

Image 图片下载配置

IMAGES_STORE = r'C:\Users\admin\PycharmProjects\cats\cats\imgs'
# image thumb size
IMAGES_THUMBS = {
# 缩略图最大宽高
'small': (90, 90),
}
# image filter size,宽高小于这个尺寸不下载
IMAGES_MIN_HEIGHT = 120
IMAGES_MIN_WIDTH = 120
# redirect download url,有些图片链接包含重定向
MEDIA_ALLOW_REDIRECTS = True

spiders 爬虫逻辑

爬虫执行的命令scrapy crawl xxx,这里的爬虫名字就是xxx_spider.py 里定义的 name 属性。 name 不需要要跟文件名一致

启动爬虫并传参

def __init__(self, page_range='1-10', *args, **kwargs):
super(xxxSpider, self).__init__(*args, **kwargs)
self.start, self.end = page_range.split('-')

启动命令大概是 scrapy crawl xxx -a page_range=1-5

传多个参数的方法暂时没有找到很好的解决方法,因此利用参数序列化成为一个参数的方式。不知道是不是因为window-cmd的关系。

yieldreturn

刚学python,因此对 yield 一开始没有概念。个人觉得在爬虫这个场景下,可以这么理解:

  • Return : 立即返回一个 request 请求(或返回一个 item)
  • Yield : 注册一个 request 请求(或一个 item),供后面的逻辑管道处理

    因此需要返回多个请求(item)的用yield,相当于一个请求列表;确定只有一个请求,可以用return(yield 应该也没问题)

Xpathcss

  • .extract() 获取一个目标列表,.extract_first() 获取列表第一个元素

  • 获取标签内容:.css('div::text'),.xpath('//div/text()')

  • 获取标签属性:.css('a::attr(href)'),.xpath('//a/@href')

  • xpath 比 css 要更快一些,css 选择器会被解释为 xpath 选择器

  • 注释内容无法通过 text() 获取,尝试通过获取整个元素再去掉 然后重新构造选择器,比如 抓取百度贴吧的时候它的源码是这样的:
      <html>....</html>
    <code id="..." class="..."><!--
    <ul class="...">
    <li>......</li>
    </ul>
    --></code>

    看起来像是用了某种前端框架,真实 html 内容被放在了 标签 并注释掉了。这时直接使用 xpath 是无法获取 code 里的 html 内容的

      thread_list = res.xpath('//html/code[@id="pagelet_html_frs-list/pagelet/thread_list"]').extract_first()
    # 去掉注释
    exp = re.compile(r'<code.*><!--(.*)--></code>', re.I|re.M|re.S)
    thread_list = re.sub(exp, r'\1', thread_list)
    # 重新加载内容
    topic = Selector(text=thread_list).xpath('//a[@class="j_th_tit "]')

其他

  • scrapy 为我们造好了绝大部分轮子,我们需要做的就是熟悉它。
  • 需要自己开发的功能,主要是研究如何从目标站点的html结构中获取自己需要的内容,以及对应的存储逻辑
  • 其他一些开发,可能是遇到特殊的反爬虫策略,也可能是对 scrapy 的部分功能还不够熟悉

Scrapy 框架进阶笔记的更多相关文章

  1. Scrapy框架学习笔记

    1.Scrapy简介 Scrapy是用纯Python实现一个为了爬取网站数据.提取结构性数据而编写的应用框架,用途非常广泛. 框架的力量,用户只需要定制开发几个模块就可以轻松的实现一个爬虫,用来抓取网 ...

  2. Scrapy 框架 (学习笔记-1)

    环境: 1.windows 10 2.Python 3.7 3.Scrapy 1.7.3 4.mysql 5.5.53 一.Scrapy 安装 1. Scrapy:是一套基于Twisted的一部处理框 ...

  3. scrapy框架使用笔记

    目前网上有很多关于scrapy的文章,这里我主要介绍一下我在开发中遇到问题及一些技巧: 1,以登录状态去爬取(带cookie) -安装内容: brew install phantomjs (MAC上) ...

  4. scrapy爬虫框架学习笔记(一)

    scrapy爬虫框架学习笔记(一) 1.安装scrapy pip install scrapy 2.新建工程: (1)打开命令行模式 (2)进入要新建工程的目录 (3)运行命令: scrapy sta ...

  5. Python爬虫进阶三之Scrapy框架安装配置

    初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此整理如下. Windows 平台: 我的系统是 ...

  6. Python爬虫进阶之Scrapy框架安装配置

    Python爬虫进阶之Scrapy框架安装配置 初级的爬虫我们利用urllib和urllib2库以及正则表达式就可以完成了,不过还有更加强大的工具,爬虫框架Scrapy,这安装过程也是煞费苦心哪,在此 ...

  7. Python爬虫进阶(Scrapy框架爬虫)

    准备工作:           配置环境问题什么的我昨天已经写了,那么今天直接安装三个库                        首先第一步:                           ...

  8. PYTHON 爬虫笔记十一:Scrapy框架的基本使用

    Scrapy框架详解及其基本使用 scrapy框架原理 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 其可以应用在数据挖掘,信息处理或存储历史数据等一系列的程序中.其最初是为了 ...

  9. 爬虫写法进阶:普通函数--->函数类--->Scrapy框架

    本文转载自以下网站: 从 Class 类到 Scrapy https://www.makcyun.top/web_scraping_withpython12.html 普通函数爬虫: https:// ...

随机推荐

  1. JS字符串转换成数字

    方法主要有三种 转换函数.强制类型转换.利用js变量弱类型转换. 1. 转换函数: js提供了parseInt()和parseFloat()两个转换函数.前者把值转换成整数,后者把值转换成浮点数.只有 ...

  2. poj 1080 Human Gene Functions(lcs,较难)

    Human Gene Functions Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 19573   Accepted:  ...

  3. HihoCoder 1636

    /** * 题目链接:https://cn.vjudge.net/problem/HihoCoder-1636 * 题目意思,石子合并,每次可以合并相邻的石子.每次可以x堆合并为一堆. * x属于[l ...

  4. 如何在MySQl数据库中给已有的数据表添加自增ID?

    由于使用MySQL数据库还没有多久的缘故,在搭建后台往数据库导入数据的时候发现新增的表单是没有自增id的,因次就有了上面这个问题. 解决方法 1.给某一张表先增加一个字段,这里我们就以node_tab ...

  5. uimsbf和 bslbf的含义

    bslbf代表位串,即“Bit string, left bit first ”, uimsbf代表无符号整数,即”unsinged integer, most significant bit fir ...

  6. ACM学习历程—FZU2148 Moon Game(计算几何)

    Moon Game Description Fat brother and Maze are playing a kind of special (hentai) game in the clearl ...

  7. 51nod 1149 Pi的递推式 组合数

    题目大意: \(F(x) = 1 (0 \leq x < 4)\) \(F(x) = F(x-1) + F(x-\pi) (4 \leq x)\) 给定\(n\),求\(F(n)\) 题解: 我 ...

  8. bzoj 2510: 弱题 概率期望dp+循环矩阵

    题目: Description 有M个球,一开始每个球均有一个初始标号,标号范围为1-N且为整数,标号为i的球有ai个,并保证Σai = M. 每次操作等概率取出一个球(即取出每个球的概率均为1/M) ...

  9. BZOJ2288:[POJ Challenge]生日礼物

    浅谈堆:https://www.cnblogs.com/AKMer/p/10284629.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...

  10. BZOJ3039:玉蟾宫

    浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...