下载器中间件的介绍
方法
随机更换请求头
中间件代码
爬虫代码
设置随机代理IP
代码实现
无限制爬取猎聘网实例
爬虫liepin.py
# -*- coding: utf-8 -*-
import scrapy
from scrapy.spiders.crawl import CrawlSpider,Rule
from scrapy.linkextractors import LinkExtractor
from ..items import ZhaopinItem
class LiepinSpider(CrawlSpider):
name = 'liepin'
allowed_domains = ['liepin.com']
start_urls = ['https://www.liepin.com/zhaopin/?key=python']
# https://www.liepin.com/job/1919503055.shtml
rules = (
Rule(LinkExtractor(allow=r'https://www.liepin.com/job/\d+\.shtml.*',restrict_xpaths=['//ul[@class="sojob-list"]//a']),callback='parse_job',follow=False),
Rule(LinkExtractor(allow=r'/zhaopin/.+curPage=\d+',restrict_xpaths=['//div[@class="pagerbar"]//a']),follow=True)
)
def parse_job(self, response):
title = response.css(".title-info h1::text").get()
company = response.css(".title-info h3 a::text").get()
city_list = response.css(".basic-infor span::text").getall()
city = "".join(city_list).strip()
edu = response.css(".job-qualifications span:nth-child(1)::text").get()
work = response.css(".job-qualifications span:nth-child(2)::text").get()
desc_list = response.css(".content-word::text").getall()
desc = "".join(desc_list).strip()
item = ZhaopinItem(title=title,company=company,city=city,edu=edu,work=work,desc=desc)
yield item
items.py
pipelines.py
models.py
用来获取代理ip地址、代理过期时间、代理是否被拉黑等信息
middlewares.py
# -*- coding: utf-8 -*-
# Define here the models for your spider middleware
#
# See documentation in:
# https://doc.scrapy.org/en/latest/topics/spider-middleware.html
from scrapy import signals
import requests
from .models import ProxyModel
import threading
import time
class IPDownloaderMiddleware(object):
def __init__(self):
super(IPDownloaderMiddleware, self).__init__()
self.current_proxy = None
self.update_proxy_url = 'http://d.jghttp.golangapi.com/getip?num=1&type=2&pro=&city=0&yys=0&port=11&time=1&ts=1&ys=0&cs=0&lb=1&sb=0&pb=45&mr=1®ions='
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.131 Safari/537.36'
}
self.update_proxy()
self.lock = threading.Lock()
# 创建一个多线程:专门用来管理代理的
# 管理方式:只要这个代理的时间超过了1分钟,或者是这个代理被拉黑了,那么在多线程中就要更换代理了
th = threading.Thread(target=self.update_proxy_in_thread)
th.start()
def process_request(self, request, spider):
# 更换代理,是在请求之前更换,也就是在这个函数中更换的
request.meta['proxy'] = self.current_proxy.proxy_url
def process_response(self, request, response, spider):
# 在响应中,通过判断状态码,来判断是否需要更新代理
if response.status != 200:
# 标记某个标记位,要更新代理了
self.lock.acquire()
self.current_proxy.is_blacked = True
self.lock.release()
# 如果这个请求没有被正确的响应到,那么应该重新返回,等待下一次重新请求获取
return request #中间件链将停止,并重新调度返回的请求,即重新执行这个类,以便将来下载。
# 如果是正常的响应,那么一定要记得返回response,否则在爬虫中获取不到
return response
def update_proxy(self):
resp = requests.get(self.update_proxy_url, headers=self.headers)
proxy_model = ProxyModel(resp.json())
self.current_proxy = proxy_model
print("更新了新的代理:%s"%self.current_proxy.proxy_url)
def update_proxy_in_thread(self):
# 管理方式:只要这个代理的时间超过了1分钟,或者是这个代理被拉黑了,那么在多线程中就要更换代理了
count = 0
while True:
time.sleep(10)
if count >= 6 or self.current_proxy.is_blacked:
self.update_proxy()
count = 0
else:
count += 1
print("count+1=%d"%count)
分布式爬虫
爬取步骤:Spiders -> Scheduler -> redis(调度和去重)-> Schedule -> Downloader -> Spider -> pipelines -> redis(下载数据)
Redis介绍
redis是一种支持分布式的nosql数据库,他的数据是保存在内存中,同时redis可以定时把内存数据同步到磁盘,即可以将数据持久化,有丰富的的数据结构(string,list列表[队列和栈],set[集合],sorted set[有序集合],hash(hash表))
nosql数据库:非关系型数据库
redis配置
- 再Ubuntu上安装redis:sudo apt install redis-server
- 连接redis服务器:redis-cli -h [ip地址] -p [端口号]
- 在其他电脑上连接本机的redis服务器:在/etc/redis/redis.conf中,修改bind,把redis服务器的ip地址加进去
爬虫部署
- 在服务器(linux)上安装scrapyd:pip3 install scrapyd
- 从/usr/local/lib/python3.6/dist-packages/scrapyd下拷贝出default_scrapyd.conf放到/etc/scrapyd/scrapyd.conf。如果没有这个配置文件,自己创建一个即可。
- 修改/etc/scrapyd/scrapyd.conf中的bind_address为自己的ip地址
- 在开发机上(自己的Windows电脑上)安装pip install scrapyd-client
- 修改python/Script/scrapyd-deploy为scrapyd-deploy.py
- 在项目中,找到scrapy.cfg,然后配置如下
`
[settings]
default = lianjia.settings
[deploy]
url = http://服务器的IP地址:6800/
project = lianjia`
- 在项目所在的路径执行命令:D:\python38\Scripts\scrapyd-deploy.py,生成版本号
- 在cmd中使用命令发布爬虫:curl http://服务器的IP地址:6800/schedule.json -d project=项目名称 -d spider=爬虫名称
如果修改了代码,那么需要重新部署,重新发布爬虫
运行分布式爬虫