scrapy基础知识

scrapy简单介绍:

  • 基于twisted异步io框架,性能是最大的优势
  • 可以加入request和beautifulsoup
  • 方便扩展,提供了很多内置功能
  • 内置的css和xpath selector非常方便
  • 默认深度优先

分析页面

  • 国内用百度,国外用Google, 不同的国家收录的页面数量不一样, 访问百度页面,输入site: www.***.com查看收录的页面
  • 分析不同页面间的Cookies传递
  • 利用sitemap分析网站结构和估算, 可以在/robots.txt中找到
  • 查看json数据以及源码和渲染之后的页面,查看提交的方式有没有js函数,还有初始加载的js文件,找到规律规则

Scrapy选择器:

  • response.css()
    • response.css(“div.quote”) 查找div块class等于quote
    • response.css(“div.tags a.tag::text”) 查找div块等于tags并且子元素a标签class也等于tag
  • response.xpath()
  • response.re() 返回unicode字符串列表, 使用re函数会有小的性能损失

Scrapy选择器内置方法

css选择器和xpath选择器可以互相嵌套

路径表达式结果
选择器表达式.extract()获得选择器数组
选择器表达式.extract_first()获取数组里第一个值,没有值默认为None
re_first()提取第一个匹配的字符串
//div/@href获取所有div下的href属性值(用于xpath选择器)
//div/text()获取所有div下的文本(用于xpath选择器)
div.quote ::text获得class值为quote的div块下的文本(用于css选择器)
div.quote ::attr(href)获得class值为quote的div块下的href属性值(用于css选择器)
//input[start-with(@id,‘fuck’)]匹配id以fuck开头的元素,id=‘fuckyou’
//input[ends-with(@id,‘fuck’)]匹配id以fuck结尾的元素,id=‘youfuck’
//input[contains(@id,‘fuck’)]匹配id中含有fuck的元素,id=‘youfuckyou’
//div/last()选取div块最后一个元素
//div[position()< 3]选取当前元素下最前面的两个子元素

注意//node[1]和(//node)[1]之间的区别


Scrapy带UA调试启动

scrapy shell -s 'User_Agent'="UA" www.baidu.com

页面追踪:

yield response.follow(相对url, callback=self.parse)

对于<a>元素,有一个简单方式: response.follow会自动使用它们的href属性。因此,代码可以进一步缩短

for a in response.css('li.next a'):
    yield response.follow(a, callback=self.parse)

IDE调试爬虫

在spider项目里创建个main文件, 把下面添加进去,

from scrapy.cmdline import execute
execute(["scrapy", "crawl", "spider"])

Windows下定时轮询爬虫

from os import system
system("scrapy crawl spider")

log调试

self.logger.info('调试')

self.log('调试')

Spider接收参数

终端传递参数

scrapy crawl spider -a='arg' -b='kwarg'

在Spider里接收参数

import scrapy

class MySpider(scrapy.Spider):
    name = 'myspider'

    def __init__(self, a=None, b=None, *args, **kwargs):
        super(MySpider, self).__init__(*args, **kwargs)
        self.a = a
        self.b = b
        # ...

spider参数只能是字符串


Scrapy shell调试response

from scrapy.shell import inspect_response

def parse_details(self, response):
    item = response.meta.get('item', None)
    if item:
        # 填充更多 `item` 字段
        return item
    else:
        inspect_response(response, self)	# scrapy shell调试resposne

浏览器打开源代码网页

from scrapy.utils.response import open_in_browser

def parse_details(self, response):
    if "item name" not in response.body:
        open_in_browser(response)	# 打开源代码网页

单独设置每个spider的settings

class MySpider(scrapy.Spider):
    name = 'myspider'

    custom_settings = {
        'SOME_SETTING': 'some value',
    }

访问spider的全局settings

class MySpider(scrapy.Spider):
    name = 'myspider'
    start_urls = ['http://example.com']

    def parse(self, response):
        print(u"现有的设置: %s" % self.settings.attributes.keys())

注意!!!
settings属性是在初始化spider之后在基本spider类中设置的。
如果您想在初始化之前使用这些设置(例如,在您的spider的__init__()方法中),
您需要覆盖from_crawler()方法。

class MyExtension(object):
    def __init__(self, log_is_enabled=False):
        if log_is_enabled:
            print(u"log已经激活!")

    @classmethod
    def from_crawler(cls, crawler):
        settings = crawler.settings
        return cls(settings.getbool('LOG_ENABLED'))

settings对象可以像dict一样使用(例如,settings[‘LOG_ENABLED’]),但是通常首选使用Settings API提供的方法提取设置,以避免类型错误。

Extensions(扩展)例子

import logging
from scrapy import signals
from scrapy.exceptions import NotConfigured

logger = logging.getLogger(__name__)

class SpiderOpenCloseLogging(object):

    def __init__(self, item_count):
        self.item_count = item_count
        self.items_scraped = 0

    @classmethod
    def from_crawler(cls, crawler):
        # 首先检查extension是否应该被启用,否则抛出notconfigure
        if not crawler.settings.getbool('MYEXT_ENABLED'):
            raise NotConfigured

        # 从settings中获取items的数量
        item_count = crawler.settings.getint('MYEXT_ITEMCOUNT', 1000)

        # 实例化extension对象
        ext = cls(item_count)

        # 将extension对象连接到signals
        crawler.signals.connect(ext.spider_opened, signal=signals.spider_opened)
        crawler.signals.connect(ext.spider_closed, signal=signals.spider_closed)
        crawler.signals.connect(ext.item_scraped, signal=signals.item_scraped)

        # 返回extension对象
        return ext

    def spider_opened(self, spider):
        logger.info(u"打开spider %s", spider.name)

    def spider_closed(self, spider):
        logger.info(u"关闭spider %s", spider.name)

    def item_scraped(self, item, spider):
        self.items_scraped += 1
        if self.items_scraped % self.item_count == 0:
            logger.info(u"已经抓取了 %d items", self.items_scraped)

Signals(信号)

from scrapy import signals
from scrapy import Spider


class DmozSpider(Spider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/",
    ]


    @classmethod
    def from_crawler(cls, crawler, *args, **kwargs):
        spider = super(DmozSpider, cls).from_crawler(crawler, *args, **kwargs)
        crawler.signals.connect(spider.spider_closed, signal=signals.spider_closed)
        return spider


    def spider_closed(self, spider):
        spider.logger.info('Spider closed: %s', spider.name)


    def parse(self, response):
        pass

暂停与重启

不同的spider不能共用一个目录(也包括run),暂停中间状态包括之前没有做完的requests,之前过滤器的filter,哪些已经看过了,还有spider状态,提供相关的信息放到这个目录下面

第一次结束的时候以什么目录开始,启动的时候就以什么样继续,就可以继续爬取

开始新的爬虫只要换新的目录就可以

在shell里面启动能发出contortsit命令,在linux里面结束进程kill -f会发出中断的信号可以进行后续的处理, kill -f -9会强制杀掉进程, 无法接收中断的信号, 做不到善后的工作

scrapy crawl spider -s JOBDIR=路径/文件

Request.meta特殊键

download_timeout在超时之前,downloader将等待最大时间(秒)
download_latency用于获取response的时间
max_retry_times每个request的重试次数, max_retry_times meta键比RETRY_TIMES settings优先级更高。
dont_redirect默认False, 是否根据response状态处理重定向

Scrapy Settings

LOG_ENABLED开启log日志
LOG_ENCODING同上, 设置log的编码, 默认utf-8
LOG_FILE设置输出log文件的名称(也可以在命令-s 显式设置文件名), 默认'None'
LOG_FORMAT用于格式化日志消息的字符串, 默认'%(asctime)s [%(name)s] %(levelname)s: %(message)s'
LOG_DATEFORMAT用于格式化日期/时间的字符串,以LOG_FORMAT展开%(asctime)s的占位符
LOG_LEVELlog的最低级别。默认'DEBUG', 可用的级别是:CRITICAL(关键级别)、ERROR(错误级别)、WARNING(警告级别)、INFO(信息级别)、DEBUG(调试级别)
LOG_STDOUT默认False, 如果为True,进程的所有标准输出(和错误)将被重定向到日志。例如,如果您print 'hello',它将出现在Scrapy log中。
LOG_SHORT_NAMES默认False, 如果为True,日志只包含根路径。如果设置为False,则显示负责日志输出的组件
****************************************************
CONCURRENT_ITEMSItems并行处理的最大数量, 默认100
CONCURRENT_REQUESTS并发request的最大数量, 默认16
CONCURRENT_REQUESTS_PER_DOMAIN对domain执行的最大并发数量, 默认8
CONCURRENT_REQUESTS_PER_IP限制单个ip最大的并发request数量, 默认0
****************************************************
DOWNLOAD_DELAY每个request的下载延迟, 默认0
DOWNLOAD_TIMEOUTrequest最大全局超时时间, 默认180秒(也可以使用Request.meta键来单独为request设置超时时间)
****************************************************
MEMDEBUG_ENABLED默认'False', True启用内存调试
*****************************************************
COOKIES_ENABLED默认True, 保持session会话
*****************************************************
RETRY_ENABLED默认False, 是否启用重试middleware
RETRY_TIMES默认2, 除了第一次下载外, 重试的最多次数
RETRY_HTTP_CODES默认: [500, 502, 503, 504, 408]状态需要重试
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

葬爱程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值