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()  # 开始运行,直到计划时间队列变成空为止

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352

推荐阅读更多精彩内容

  • 目的是爬取Weight Loss里面的文章。(自己写报告用,不宜作为学习) 内容包括{标题,副标题,作者,头像,日...
    46H阅读 915评论 0 0
  • scrapy源码https://github.com/scrapy/scrapy/tree/master/scra...
    木鱼非鱼阅读 826评论 0 1
  • 一个完整的爬虫程序,应该包含五个部分,分别是负责url链接管理的URL管理器,负责获取网络数据的Downloade...
    zhile_doing阅读 342评论 0 1
  • 睡觉这件事,很简单,也有些复杂。复杂的并不是睡觉本身这个动作,而是睡觉因人而异的复杂度。 有些人睡觉,外界的环境的...
    贪囍阅读 49评论 0 1
  • 每做件事情都不是那么容易的,但你有想法就一定要去尝试一下不是吗?一个没有把百酒尝遍的人,是不大懂得清水之味的。一开...
    ymqs千山墨阅读 496评论 0 0