scrapy常用操作

# Linux

pip3 install scrapy

# windows版本

1.pip install wheel

2.下载

https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml

pip install C:\Users\Administrator\Desktop\lxml-4.4.1-cp37-cp37m-win_amd64.whl

3.下载

https://www.lfd.uci.edu/~gohlke/pythonlibs/#Twisted

pip install C:\Users\Administrator\Desktop\Twisted-19.10.0-cp37-cp37m-win_amd64.whl

4.下载 (一定要下对应版本)

https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/

安装(无脑下一步)

5.pip install scrapy

------------------

#设置settings.py

------

FEED_EXPORT_ENCODING = 'utf-8' #'GB2312' #设置编码

DEPTH_LIMIT=1 #设置调度器遍历层级

ROBOTSTXT_OBEY = False # 是否遵行robots协议,设置False允许爬取所有,默认为True,表示遵守

# USER_AGENT 是伪装访问者信息

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/49.0.2623.221 Safari/537.36 SE 2.X MetaSr 1.0'

DOWNLOAD_DELAY = 3 #请求延迟,多少秒执行一次

COOKIES_ENABLED = True #是否拿到cookie,默认是True

#设置请求限速

AUTOTHROTTLE_ENABLED = True #自动限速扩展(实现上一个请求和下一个请求的时间是不固定的,默认为False

AUTOTHROTTLE_START_DELAY = 5 #初始的下载延时默认5秒

AUTOTHROTTLE_MAX_DELAY = 60 #最大下载延时

AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0 #针对网站最大的并行请求数量

AUTOTHROTTLE_DEBUG = False #调试模式(可以展示每个response每个限速时间)默认为False

#设置缓存

HTTPCACHE_ENABLED = True #是否启用缓存

HTTPCACHE_EXPIRATION_SECS = 0 #设置超时时间

HTTPCACHE_DIR = 'httpcache' #缓存路径

HTTPCACHE_IGNORE_HTTP_CODES = [] #缓存忽略的http状态码

HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage' #缓存启用插件

--------

#创建项目

scrapy startproject app

#创建起始文件

scrapy genspider chouti dig.chouti.com # chouti名字 dig.chouti.com 网址

#运行

scrapy crawl chouti --nolog #加--nolog不显示日志 chouti名字

-----

chouti.py

---------

from scrapy.selector import Selector

from scrapy.http import Request

from ..items import ChoutiItem # 使用pipeline做缓存,持久化

class ChoutiSpider(scrapy.Spider):

    name = 'chouti' #不能省略,是运行命令的名字

    allowed_domains = ['www.htqyy.com'] #允许的域名

    start_urls = ['http://www.htqyy.com/genre/11'] #起始地址

    #def start_request(self): #可以重写初始请求

    #    for url in self.start_urls:

    #        yield Request(url,callback=self.parse)

    def parse(self, response):

        hxs=Selector(response=response).xpath('//a[@class="link"]').extract()  # .extract()获取内容,默认是类

        for i in hxs:

            print(i)

    def next_page(self,url):

        # 将新要访问的url添加到调度器(固定语法)

        yield Request(url=url,callback=self.getName)

    def getName(self, response):

        hxs=Selector(response=response).xpath('//script[@type="text/javascript"]/text()').extract()

        for v in hxs:

            url=re.search(r"var name = [\"\'](.+?)[\"\']"v,re.S)

            if url:

                name=url.group(1)

                item_obj = ChoutiItem(name=name) # 配置pipeline缓存字段

                yield item_obj

------------------------------             

items.py # 配置pipeline缓存字段

-----

import scrapy

import scrapy.http.Cookies import CookieJar #获取设置cookie用

class ChoutiItem(scrapy.Item):

    name = scrapy.Field() #缓存字段


    #def parse(self,response):

    #    cookie_obj=CookieJar()

    #    cookie_obj.extract_cookies(response,response.request)

    #    print(cookie_obj._cookies) #获取所有cookies

-----

setttings.py 添加要使用的pipeline缓存

----

ITEM_PIPELINES = {

  'app.pipelines.AppPipeline': 200, #那个值小先执行那个

  'app.pipelines.AppPipeline2': 300,

}

注:配置里变量都需要大写否则读取不到

----

pipelines.py 使用缓存

---------

class AppPipeline(object):

    def __init__(self,conn_str):

        self.conn_str=conn_str

    @classmethod

    def from_crawler(cls,crawler):

        #初始化用于创建pipline对象,并读取配置文件

        val=crawler.settings.getint('xxx') #获取settings.py配置信息

        return cls(val) #相当于调用 __init__

    def open_spider(self, spider):

        #爬虫开始时被调用

    def clese_spider(self, spider):

        #爬虫关闭时被调用

    def process_item(self, item, spider):

        #每当数据需要持久化时,被调用(每次缓存都调用)

        print("da=>",item.get('name'))

        #加return item 会执行下个AppPipeline2不加不执行

        #return item

class AppPipeline2(object):

    ...

------------

# 请求对象

from scrapy.http import Request

Request(url, #请求的URL

callback=self.getName, #请求的响应回调,下载内容为第一个参数

method ='GET', #请求方法,默认为'GET',要大写的

headers = {}, #请求头,字典格式

body = None, #包含请求主体的str

Cookies = {}, # {}或[{},{}] 请求cookie

meta = {'data':111}, #设置携带的参数,可以通过response拿到

encoding ='utf-8', #请求的编码(默认为'utf-8')

priority = 0, #请求的优先级(默认为0),较高值优先

dont_filter = False,

errback = self.getName, #异常回调,第一个参数为错误信息

flags = None,

cb_kwargs = None)

----------

# response 响应参数

def getName(self, response):

参数:

response.meta.get('data') #获取携带的参数

response.url #请求地址

response.text #响应主体,为unicode

response.body #始终是一个字节对象

response.meta={'depth':1} #depth 响应深度

response.status #响应的HTTP状态

response.headers #响应头

-----------

# 采集html数据 xpath 两种方式

from scrapy.selector import Selector

Selector(response=response).xpath('//title/text()').extract() #老版方式

response.xpath('//title/text()').extract() #直接响应里取

# xpath('//') 选择器:

----

//  表示子孙中

.//  当前对象的子孙中

/    儿子

/div 儿子中的div标签

/div[2] 儿子中的div第二个标签

/div[@id]  儿子中的div标签有id的

/div[@id="i1"]  儿子中的div标签且id=i1

/div[@id="i1"]  儿子中的div标签且id=i1

obj.extract()        # 列表中的每一个对象转换字符串 =》 []

obj.extract_first()  # 列表中的每一个对象转换字符串 => 列表第一个元素

//div/text()    获取某个标签的文本

a/@href  获取属性

//a[starts-with(@href, "/all/hot/recent/")]/@href'  已xx开始

//a[re:test(@href, "/all/hot/recent/\d+")]          正则     

----------

#设置代理ip

-----

1.项目根目录下面创建了一个myproxy.py的文件用于存放自定义的代理相关的类。

import random,base64

def to_bytes(text, encoding=None, errors='strict'):

        if isinstance(text, bytes):

            return text

        if not isinstance(text, six.string_types):

            raise TypeError('to_bytes must receive a unicode, str or bytes '

                            'object, got %s' % type(text).__name__)

        if encoding is None:

            encoding = 'utf-8'

        return text.encode(encoding, errors)

class OneProxyMiddleware(object):

    def process_request(self, request, spider):

        PROXIES = [

            {'ip_port': '111.11.228.75:80', 'user_pass': ''},

            {'ip_port': '120.198.243.22:80', 'user_pass': ''},

            {'ip_port': '111.8.60.9:8123', 'user_pass': ''},

            {'ip_port': '101.71.27.120:80', 'user_pass': ''},

            {'ip_port': '122.96.59.104:80', 'user_pass': ''},

            {'ip_port': '122.224.249.122:8088', 'user_pass': ''},

        ]

        proxy = random.choice(PROXIES)

        if proxy['user_pass'] is not None:

            request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])

            encoded_user_pass = base64.b64encode(to_bytes(proxy['user_pass']))

            request.headers['Proxy-Authorization'] = to_bytes('Basic ' + encoded_user_pass)

        else:

            request.meta['proxy'] = to_bytes("http://%s" % proxy['ip_port'])

2.settings.py里面添加扩展

DOWNLOADER_MIDDLEWARES = {

    'app.myproxy.MyProxyMiddleware': 100

}

------

#https自定义证书

------

Https访问时有两种情况:

1.要爬取网站使用的可信任证书(默认支持)

DOWNLOADER_HTTPCLIENTFACTORY = "scrapy.core.downloader.webclient.ScrapyHTTPClientFactory"

DOWNLOADER_CLIENTCONTEXTFACTORY = "scrapy.core.downloader.contextfactory.ScrapyClientContextFactory"

2.要爬取网站使用的自定义证书

DOWNLOADER_HTTPCLIENTFACTORY = "scrapy.core.downloader.webclient.ScrapyHTTPClientFactory"

DOWNLOADER_CLIENTCONTEXTFACTORY = "app.https.MySSLFactory"

# https.py

from scrapy.core.downloader.contextfactory import ScrapyClientContextFactory

from twisted.internet.ssl import (optionsForClientTLS, CertificateOptions, PrivateCertificate)

class MySSLFactory(ScrapyClientContextFactory):

    def getCertificateOptions(self):

        from OpenSSL import crypto

        # open('/Users/... 放配置文件的目录

        v1 = crypto.load_privatekey(crypto.FILETYPE_PEM, open('/Users/client.key.unsecure', mode='r').read())

        v2 = crypto.load_certificate(crypto.FILETYPE_PEM, open('/Users/client.pem', mode='r').read()) #读取配置文件

        return CertificateOptions(

            privateKey=v1,  # pKey对象

            certificate=v2,  # X509对象

            verify=False,

            method=getattr(self, 'method', getattr(self, '_ssl_method', None))

        )

--------

#做定时任务

----------

1.最简单的方法:直接使用Timer类

import time

import os

while True:

    os.system("scrapy crawl chouti --nolog")

    time.sleep(86400)  #每隔一天运行一次 24*60*60=86400s

2.使用标准库的sched模块

import sched

#初始化sched模块的scheduler类

#第一个参数是一个可以返回时间戳的函数,第二个参数可以在定时未到达之前阻塞。

schedule = sched.scheduler ( time.time, time.sleep )

#被周期性调度触发的函数

def func():

    os.system("scrapy crawl News")

def perform1(inc):

    schedule.enter(inc,0,perform1,(inc,))

    func()    # 需要周期执行的函数

def mymain():

    schedule.enter(0,0,perform1,(86400,))

if __name__=="__main__":

    mymain()

    schedule.run()  # 开始运行,直到计划时间队列变成空为止

你可能感兴趣的:(scrapy常用操作)