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,
}

源碼地址

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章