scrapy入门到放弃(一)

scrapy 爬虫流程

scrapy 爬虫流程和一般的爬虫流程基本一样,发送url,响应提取url和数据,数据存储,url重新放到url队列中

Scrapy Engine(引擎)总指挥:负责数据和信号在不同模块之间传递scrapy实现
Scheduler(调度器)队列,存放engine发送过来的request请求scrapy实现
Downloader(下载器)下载引擎发送过来的请求,并返回给引擎scrapy实现
Spider(爬虫)处理引擎发送过来的reponse,提取数据,url,返回给引擎自己手写
Item Pipeline(管道)处理引擎传送过来的数据,存储到mongodb自己手写

Downloader Middlewares

(下载中间件)

自定义下载扩展,例:设置代理IP,user-agent自己写相关类

Spider Middlewares

(爬虫中间件)

可自定义request请求和进行response过滤一般不用手写

 

 

 

 

 

 

 

 

 

scrapy 工程创建

创建工程

scrapy startproject +项目名字

$ scrapy startproject spider_boss

创建爬虫

$ cd spider_boss

scrapy genspider  +<爬虫名字> + <允许爬取的域名>

$ scrapy genspider zhipin zhipin.com

oniondeMacBook-Pro:spider onion$ tree spider_boss/
spider_boss/
├── README.md
├── main.py              自己写的爬虫执行入口
├── scrapy.cfg
└── spider_boss
    ├── __init__.py
    ├── items.py          定义自己需要爬取的内容
    ├── middlewares.py    下载中间件添加代理
    ├── pipelines.py      管道处理数据存储
    ├── settings.py       爬虫的设置文件,下载延时,日志等级等
    └── spiders         自己定义的spider文件夹
        ├── __init__.py  
        ├── zhipin.py
        └── zhipin_test.py

scrapy文件解析

spider_boss.items.py

#spider_boss.items.py
class SpiderBossItem(scrapy.Item):
    # define the fields for your item here like:
    #需要爬取得内容
    job_title = scrapy.Field()  #一个字典
    company = scrapy.Field()
    money = scrapy.Field()
    job_context = scrapy.Field()
    detail_url=scrapy.Field()

#获取数据的时候,使用不同的item来存放不同的数据
#在数据交给pipeline 的时候,可以通过isnstance(item,SpiderBossItem)来判断属于哪个item,进行不同的数据(item)处理

 

spiders.zhipin.py

从选择器中提取字符串

1.extract()  返回一个包含有字符串数据的列表

2.extract_first()  返回列表中的第一个字符串

注意:

spider中的parse方法名不能修改

爬取得url必须是属于allowed_domains下的链接

response.xpath()返回的是一个含有selector对象的列表

scrapy.request():

scrapy.Request(url,[callback,meta,dont_filter=False,...])
常用参数:
callback:指定传入的url交给哪个解析函数去处理
meta:实现在不同解析函数中传递数据,meta 会默认带部分信息,如下载延迟,请求深度(settings中配置)等
dont_filter:让scrapy 是否过滤当前url,默认False,带去重功能,如果需要重复请求某个url,需要置True

#scrap.Request()函数定义
class Request(object_ref):

    def __init__(self, url, callback=None, method='GET', headers=None, body=None,
                 cookies=None, meta=None, encoding='utf-8', priority=0,
                 dont_filter=False, errback=None, flags=None):

 

#spiders.zhiping.py

class ZhipinSpider(scrapy.Spider):
    name = 'zhipin'  #爬虫名 <scrapy crawl zhipin>
    allowed_domains = ['zhipin.com']  #允许爬的域名,防止爬到其他网站
    start_urls = ['http://zhipin.com/job_detail/?query=python'] #开始爬取的地址

    def parse(self, response):  #接收下载中间件传来的response
        info_list = response.xpath('//div[@class="job-list"]//li')
        for each in info_list:
            item = SpiderBossItem() #item中定义需要爬去的内容
            item["company"] = each.xpath('.//div[@class="company-text"]/h3//text()').extract_first()
            item["job_title"] = each.xpath('.//div[@class="job-title"]/text()').extract_first()
            item["money"] = each.xpath(".//span/text()").extract_first()
            item["detail_url"] = each.xpath('.//div[@class="job-title"]/../@href').extract_first()
            item["detail_url"] = "https://www.zhipin.com" + item["detail_url"]
            # logger.warning(item)
            # 回调处理职位详情页
            yield scrapy.Request(
                item["detail_url"],
                callback=self.parse_context_detail,
                meta={"item": item}# 将这里的item传送给parse_context_detail中继续处理,
#这里传过去的是同一个item,如果你不想下次的处理影响当前item,使用deepcopy 例: meta={"item":deepcopy(item)}
            )
            # next page
        next_url = response.xpath("//a[@class='next']/@href").extract_first()

        if next_url is not None:
            next_url = "https://www.zhipin.com" + next_url
            yield scrapy.Request(
                next_url,
                callback=self.parse
            )

    def parse_context_detail(self, response):
        item = response.meta["item"] #接收parse中的item
        item["job_context"] = response.xpath("//div[@class='job-sec']/div//text()").extract()
        # print(item)
        yield item   #传送个管道处理数据

spider_boss.pipelines.py

管道权重越小,优先级越高

pipeline  process_item()方法不能修改为其他名称

#spider_boss.pipelines.py

class SpiderBossPipeline(object):

    def open_spider(self, spider): #爬虫开始会调用一次
        #mongodb的配置个可以放在settings.py文件中管理 
        self.client = MongoClient("mongodb://127.0.0.1:27017/boss")

    def close_spider(self, spider): #爬虫结束会调用
        print("close ...")
        print(spider.name)
        self.client.close()

    def process_item(self, item, spider): #item参数  spider yield item 过来的
     
        if spider.name =="zhipin":
            self.collection = self.client["boss"]["python"]
            item["job_context"] = self.process_context(item["job_context"])
            # collection.insert(item)
            if isinstance(item, SpiderBossItem):
                self.collection.insert(dict(item)) #数据存储到mongodb中
            # print(item)
        return item

    def process_context(self, context):
        # 处理 "\n" 和空字符串
        context = [i.strip() for i in context if i.strip() != ""]
        return context

管道文件写完后需要在settings.py中开启管道

spider_boss.settings.py中

#spider_boss.settings 
#: 300  值越小优先级越高
ITEM_PIPELINES = {
   'spider_boss.pipelines.SpiderBossPipeline': 300,
   'spider_boss.pipelines.SpiderBossPipeline1': 301,
}

spider_boss.middlewares.py

from scrapy import signals
import random
from scrapy.utils.project import get_project_settings


settings = get_project_settings()
class MyUserAgentMiddleware(object): #设置user-agent
    def __init__(self):
        pass
    def process_request(self, request, spider):
        # spider.logger.info(msg='now entring download midware')
        agent = random.choice(settings.get('MY_USER_AGENT_LIST'))
        if agent:
            request.headers.setdefault(b'User-Agent',agent)
        spider.logger.info(u'User-Agent is : {} {}'.format(request.headers.get('User-Agent'), request))


class IPProxyDownloadMiddleware(object):  #设置IP代理

    def process_request(self, request, spider):
        ip_proxy = random.choice(settings.get('IP_PROXY_LIST')) #获取settings文件中ip代理列表
        print('*'*20)
        print(ip_proxy)
        #添加代理需要在request的meta信息中添加proxy字段,
        #代理形式:协议+ip+端口
        request.meta["proxy"]=ip_proxy

spider_boss.settings.py中开启下载中间件和定义相关的user-agent列表和代理ip列表

MY_USER_AGENT_LIST=[
    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
  ...
]


IP_PROXY_LIST=[
    # "http://58.253.155.211:9999",
    "https://61.189.242.243:55484",
    # "http://175.44.158.72:9000"
]


DOWNLOADER_MIDDLEWARES = {
   'spider_boss.middlewares.MyUserAgentMiddleware': 543,
   'spider_boss.middlewares.IPProxyDownloadMiddleware': 542,
}

源码地址

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值