前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python scrapy学习笔记

python scrapy学习笔记

作者头像
py3study
发布2020-01-06 22:25:10
5550
发布2020-01-06 22:25:10
举报
文章被收录于专栏:python3python3

scrapy是python最有名的爬虫框架之一,可以很方便的进行web抓取,并且提供了很强的定制型。

一、安装scrapy

代码语言:javascript
复制
# pip install scrapy

二、基本使用

1、初始化scrapy项目

代码语言:javascript
复制
# scrapy startproject myscrapy

初始化完成后的目录结构

代码语言:javascript
复制
# tree
.
├── myscrapy
│   ├── __init__.py
│   ├── items.py                      # 设置数据存储模板,用于结构化数据
│   ├── middlewares.py                # 中间件,相当于钩子,对爬去前后做预处理
│   ├── pipelines.py                  # 管道模块,处理spider模块分析好的数据,如保存入库等
│   ├── settings.py                   # 配置文件,如并发数,是否开启缓存
│   └── spiders
│       ├── __init__.py
│       └── myspider.py
└── scrapy.cfg                         # 项目的配置文件

一个例子爬取当当网的首页

代码语言:javascript
复制
#!/usr/bin/python
#coding:utf-8

import scrapy

class DangDang(scrapy.Spider):
    # 必须定义
    name = "dangdang"
    # 初始urls
    start_urls = [ 
        "http://www.dangdang.com"
    ]   

    # 默认response处理函数
    def parse(self, response):      # 抓取start_urls页面,自动执行parse回调函数
        current_url = response.url  # 当前请求的URL
        body = response.body        # 请求的内容
        print '请求的URL: {}\n请求的内容: {}'.format(current_url,body)

运行

代码语言:javascript
复制
# scrapy crawl dangdang                # 方式1
# scrapy runspider dangdang.py         # 方式2

爬虫开始爬取start_urls定义的url,并输出到文件中,最后输出爬去报告,会输出爬取得统计结果

2、通过代码运行爬虫

每次进入控制台运行爬虫还是比较麻烦的,而且不好调试,我们可以通过CrawlerProcess通过代码运行爬虫,新建一个模块run.py

代码语言:javascript
复制
#!/usr/bin/python
#coding:utf-8

from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from spiders.dangdang import DangDang

# 获取setting.py模块的设置
settings = get_project_settings()
process = CrawlerProcess(settings=settings)

# 添加spider,可以多个
process.crawl(DangDang)                                                                                                                                       

# 启动爬虫,阻塞知道爬取结束
process.start()

只需要执行python run.py就可以执行爬虫

三、Scrapy类

如上面的DangDang类,爬虫类继承自scrapy.Spider

1、常用属性

  • name:爬虫的名字,必须唯一(如果在控制台使用的话,必须配置)
  • start_urls:爬虫初始爬取的链接列表
  • parse:response结果处理函数
  • custom_settings:自定义配置,覆盖settings.py中的默认配置

2、常用方法

  • start_requests:启动爬虫的时候调用,默认是调用make_requests_from_url方法爬取start_urls的链接,可以在这个方法里面定制,如果重写了该方法,start_urls默认将不会被使用,可以在这个方法里面定制一些自定义的url,如登录,从数据库读取url等,本方法返回Request对象
  • make_requests_from_url:默认由start_requests调用,可以配置Request对象,返回Request对象
  • parse:response到达spider的时候默认调用,如果在Request对象配置了callback函数,则不会调用,parse方法可以迭代返回ItemRequest对象,如果返回Request对象,则会进行增量爬取

3、Request与Response对象

  每个请求都是一个Request对象,Request对象定义了请求的相关信息(url, method, headers, body, cookie, priority)和回调的相关信息(meta, callback, dont_filter, errback),通常由spider迭代返回

  其中meta相当于附加变量,可以在请求完成后通过response.meta访问请求完成后,会通过Response对象发送给spider处理,常用属性有(url, status, headers, body, request, meta)

四、选择器

  • 基本的选择器
  • 正则选择

1、基本的选择器

  1. //                    ## 子孙
  2. /                     # 孩子
  3. //div[@class='info'][@id='1']  # 属性选择器
  4. //div/img/@src            # div下所有img的src值
  5. //div/a[1]               # div下第一个<a>
  6. //div/a[1]/text()          # div下第一个<a>的值

例如

wKioL1hiEMqhmYZ8AABFcjnhrYU527.jpg
wKioL1hiEMqhmYZ8AABFcjnhrYU527.jpg

想要获取书名,可以写为: //ul[@class='list_aa listimg']/li//a/@title

查找方式

代码语言:javascript
复制
# 方法1,即将被废弃的
from scrapy.selector import HtmlXPathSelector
hxs = HtmlXPathSelector(response)
items_HtmlXPathSelector = hxs.select('//ul[@class='list_aa listimg']/li//a/@title')
print(len(items_HtmlXPathSelector))

# 方法2
from scrapy.selector import Selector
items_Selector = Selector(response=response).xpath('//ul[@class='list_aa listimg']/li//a/@title')
print(len(items_Selector))

2、正则选择器

代码语言:javascript
复制
<body>
    <li class="item-"><a href="link.html">first item</a></li>
    <li class="item-0"><a href="link1.html">first item</a></li>
    <li class="item-1"><a href="link2.html">second item</a></li>
</body>

书写方法://li[re:test(@class, "item-\d*")]//@href

查找方式

代码语言:javascript
复制
ret = Selector(response=response).xpath('//li[re:test(@class, "item-\d*")]//@href').extract()
# re ---- 通过正则进行匹配
# test -- 匹配

五、使用scrapy爬取网站聊天记录和用户头像

代码语言:javascript
复制
#!/usr/bin/python
#coding:utf-8

import scrapy
from scrapy.selector import Selector
import os
import requests

class NextSpider(scrapy.spiders.Spider):
    name = 'nextspider'
    start_urls = ["http://group.jobbole.com/27740/#comm-77724"]

    def parse(self,response):
        items_selector = Selector(response=response)
        items = items_selector.xpath('//ul[@class="cmnt-list"]/li')
#       print items
        for i in range(len(items)):
            srcs = items_selector.xpath('//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-header"]/a/img/@src'%i).extract()
            names = items_selector.xpath('//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-header"]/div/span[1]/a/text()'%i).extract()
            msgs = items_selector.xpath('//ul[@class="cmnt-list"]/li[%d]//div[@class="cmnt-body"]/p/text()'%i).extract()                                      
            if srcs and names and msgs:
                try:
                    img_url = srcs[0]
                    filename = names[0].encode('utf-8')
                    msg = ','.join([i.encode('utf-8') for i in msgs[1:]])
                    print '用户ID: {}\n发表信息: {}'.format(filename,msg)
                    img_dir = 'imgs'
                    path = os.path.join(os.getcwd(),img_dir,filename+'.png')
                    r = requests.get(img_url)
                    with open(path,'wb') as f:
                        for chunk in r.iter_content(chunk_size=1024):
                            if chunk:
                                f.write(chunk)
                                f.flush()
                        f.close()
                except Exception,e:
                    print '错误: {}'.format(e)

结果

代码语言:javascript
复制
用户ID: 小编辑
发表信息: 恭喜!,说说你是怎么追到的。然后再打广告 :)
用户ID: 迷路的兔纸-->
发表信息: 你这是赤果果的炫耀
用户ID: sorry丶
发表信息: 10月份去九寨沟,在青旅里面遇到我的那个她。
... ...

图片

代码语言:javascript
复制
# ls imgs/
lishenluo.png  sorry丶.png  寻找隐世快乐.png  小编辑.png  忠文.png  熊绎.png  连时光都吐了.png  迷路的兔纸-->.png

六、items.py中的Item类

初始化后默认的Item类

代码语言:javascript
复制
import scrapy

class MyscrapyItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    pass

scrapy.Item的用法与python中的字典用法基本一样,只是做了一些安全限制,属性定义使用Field,这里只是进行了声明,而不是真正的属性,使用的时候通过键值对操作,不支持属性访问

七、Pipeline

spider负责爬虫的配置,item负责声明结构化数据,而对于数据的处理,在scrapy中使用管道的方式进行处理,只要注册过的管道都可以处理item数据(处理,过滤,保存)

示例:这里定义一个预处理管道PretreatmentPipeline.py,如果item的title为None,则设置为空字符串

代码语言:javascript
复制
class PretreatmentPipeline(object):
    def process_item(self, item, spider):
        if item['msgs']:
            # 不让msgs为空
            item['msgs'] = ''
        return item

八、setting.py文件

setting.py文件中为我们提供了许多自带的功能,例如缓存、多线程等等,只需要修改配置即可

1、缓存

代码语言:javascript
复制
# 打开缓存
HTTPCACHE_ENABLED = True

# 设置缓存过期时间(单位:秒)
#HTTPCACHE_EXPIRATION_SECS = 0

# 缓存路径(默认为:.scrapy/httpcache)
HTTPCACHE_DIR = 'httpcache'

# 忽略的状态码
HTTPCACHE_IGNORE_HTTP_CODES = []

# 缓存模式(文件缓存)
HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

2、多线程

代码语言:javascript
复制
# 默认Request并发数:32
CONCURRENT_REQUESTS = 32

# 默认每个域名的并发数:16
CONCURRENT_REQUESTS_PER_DOMAIN = 16

# 每个IP的最大并发数:0表示忽略
CONCURRENT_REQUESTS_PER_IP = 16
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-09-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
消息队列 TDMQ
消息队列 TDMQ (Tencent Distributed Message Queue)是腾讯基于 Apache Pulsar 自研的一个云原生消息中间件系列,其中包含兼容Pulsar、RabbitMQ、RocketMQ 等协议的消息队列子产品,得益于其底层计算与存储分离的架构,TDMQ 具备良好的弹性伸缩以及故障恢复能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档