文章目录

  • 六、模拟浏览器行为
    • 创建 useragent.py 用于选择头部请求代理
    • 在 settings.py 中开启
  • 七、设置代理 ip (中间件的方式)
    • 1、获取的代理 ip 存入 redis 数据库
      • 免费代理 ip
        • 在 items.py 中新增 ProxyItem 类
        • 快代理(kuaiProxy.py)
        • 齐云代理(qiYunProxy.py)
        • 云代理(yunProxy.py)
        • 将获取到的免费代理 ip 存入 redis 数据库
      • 付费代理 ip (ipProxy.py)
    • 2、 从 redis 数据库中随机取出一个代理 ip 用作这次请求的代理
    • 3、 在 settings.py 中开启代理 ip
    • 4、 扩展
  • 八、多管道、多蜘蛛
    • 1、 每一个 spider 需要的配置可能不一样
    • 2、 在 douban 文件夹下创建 crawls 文件夹并在该文件夹内创建 crawls.py 文件统一启动所有蜘蛛
  • 九、 Scrapy 每天定时爬取数据
    • 1、生成日志文件(控制台不输出)
    • 2、启动 spiders 的 startSpidersDaily.py 文件
    • 3、 系统启动 startSpidersDaily.py 的 bat 文件
    • 4、 设置每天的定时任务(我是 window10)
  • 十、我的资源包
    • [Scrapy 框架爬取豆瓣电影的信息(包括图片)和电影评论-3](https://download.csdn.net/download/Cappuccino_Luo/73929114)
    • [Scrapy 框架爬取豆瓣电影的信息(包括图片)和电影评论-1](https://blog.csdn.net/Cappuccino_Luo/article/details/122314266)
  • 十一、参考

六、模拟浏览器行为

创建 useragent.py 用于选择头部请求代理

# 导入random模块
import random
# 导入 useragent 用户代理模块中的 UserAgentMiddleware 类
from scrapy.downloadermiddlewares.useragent import UserAgentMiddleware# RotateUserAgentMiddleware 类,继承 UserAgentMiddleware 父类
# 作用:创建动态代理列表,随机选取列表中的用户代理头部信息,伪装请求。
# 绑定爬虫程序的每一次请求,一并发送到访问网址。# 发爬虫技术:由于很多网站设置反爬虫技术,禁止爬虫程序直接访问网页,因此需要创建动态代理,将爬虫程序模拟伪装成浏览器进行网页访问。
class RotateUserAgentMiddleware(UserAgentMiddleware):def process_request(self, request, spider):# 随机轮换 user-agentua = random.choice(self.user_agent_list)if ua:request.headers.setdefault('User-Agent', ua)# the default user_agent_list composes chrome,IE,firefox,Mozilla,opera,netscape# for more user agent strings,you can find it in http://www.useragentstring.com/pages/useragentstring.php# 编写头部请求代理列表user_agent_list = ["Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1""Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.57 ""Safari/536.11","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6","Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5","Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3","Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 ""Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3","Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24","Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 (KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24","Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0"]

在 settings.py 中开启

注: 使用下面的 DOWNLOADER_MIDDLEWARES 将 settings.py 中的 DOWNLOADER_MIDDLEWARES 进行覆盖

# Enable or disable downloader middlewares
# See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
# response 403(服务器拒绝请求) 说明人家不欢迎爬虫,这时候就需要设置 header 头部信息,用 user_agent_list 进行头部请求伪装
# useragent.py 配置到框架中去,此时框架在发送请求时,会自动添加随机的头部 user-agent 列表其中一个代理信息
# ip 存在被封的风险,所以使用代理 ip ,代理被封还有代理,代理在中间件中设置
# 数字543, 400表示中间件先被调用的次序。数字越小,越先被调用
DOWNLOADER_MIDDLEWARES = {'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,'douban.useragent.RotateUserAgentMiddleware': 400,
}

七、设置代理 ip (中间件的方式)

1、获取的代理 ip 存入 redis 数据库

免费代理 ip

在 items.py 中新增 ProxyItem 类

class ProxyItem(scrapy.Item):schema_pattern = re.compile(r'http|https$', re.I)ip_pattern = re.compile(r'^([0-9]{1,3}.){3}[0-9]{1,3}$', re.I)port_pattern = re.compile(r'^[0-9]{2,5}$', re.I)'''{"schema": "http", # 代理的类型"ip": "127.0.0.1", # 代理的IP地址"port": "8050", # 代理的端口号"original": "西刺代理", # 来源"used_total": 11, # 代理的使用次数"success_times": 5, # 代理请求成功的次数"continuous_failed": 3, # 使用代理发送请求,连续失败的次数"created_time": "2018-05-02" # 代理的爬取时间}'''schema = scrapy.Field()ip = scrapy.Field()port = scrapy.Field()original = scrapy.Field()created_time = scrapy.Field()# 检查 IP 代理的格式是否正确def _check_format(self):if self['schema'] is not None and self['ip'] is not None and self['port'] is not None:if self.schema_pattern.match(self['schema']) and self.ip_pattern.match(self['ip']) and self.port_pattern.match(self['port']):return Truereturn False# 获取IP代理的urldef _get_url(self):# 代理地址的格式化字符串PROXY_URL_FORMATTER = '%(schema)s://%(ip)s:%(port)s'return PROXY_URL_FORMATTER % {'schema': self['schema'], 'ip': self['ip'], 'port': self['port']}

快代理(kuaiProxy.py)

import datetime
import timeimport scrapy
from scrapy.cmdline import executefrom douban.items import ProxyItemclass KuaiproxySpider(scrapy.Spider):name = 'kuaiProxy'allowed_domains = ['www.kuaidaili.com']start_urls = ['https://www.kuaidaili.com/free/inha/']def parse(self, response):tr_list = response.css("div#list>table>tbody tr")for tr in tr_list:ip = tr.css("td[data-title='IP']::text").get()port = tr.css("td[data-title='PORT']::text").get()schema = tr.css("td[data-title='类型']::text").get()if schema.lower() == "http" or schema.lower() == "https":item = ProxyItem()item['schema'] = schema.strip().lower()item['ip'] = ip.strip()item['port'] = port.strip()item['original'] = '快代理'item['created_time'] = time.strftime('%Y-%m-%d', time.localtime(time.time()))if item._check_format():yield itemnext_page = response.xpath("//a[@class='active']/../following-sibling::li/a/@href").get()# 前几页都是最近更新的,我选取第1页if next_page != "/free/inha/2/":next_url = 'https://www.kuaidaili.com' + next_pageyield scrapy.Request(next_url, dont_filter=True)if __name__ == '__main__':execute(['scrapy', 'crawl', 'kuaiProxy'])# execute('scrapy crawl kuaiProxy_spider -s JOBDIR=../../crawls/kuaiProxy'.split())

齐云代理(qiYunProxy.py)

import datetime
import timeimport scrapy
from scrapy.cmdline import executefrom douban.items import ProxyItemclass QiyunproxySpider(scrapy.Spider):name = 'qiYunProxy'allowed_domains = ['proxy.ip3366.net']start_urls = ['https://proxy.ip3366.net/free/']def parse(self, response):tr_list = response.css("div.container>table>tbody tr")for tr in tr_list:ip = tr.css("td[data-title='IP']::text").get()port = tr.css("td[data-title='PORT']::text").get()schema = tr.css("td[data-title='类型']::text").get()if schema.lower() == "http" or schema.lower() == "https":item = ProxyItem()item['schema'] = schema.strip().lower()item['ip'] = ip.strip()item['port'] = port.strip()item['original'] = '齐云代理'item['created_time'] = time.strftime('%Y-%m-%d', time.localtime(time.time()))if item._check_format():yield itemnext_page = response.xpath('//div[@class="container"]/nav/ul/li/a[@aria-label="Next"]/@href').get()if next_page != "?action=china&page=2":next_url = 'https://proxy.ip3366.net/free/' + next_pageyield scrapy.Request(next_url, dont_filter=True)if __name__ == '__main__':execute(['scrapy', 'crawl', 'qiYunProxy'])# execute('scrapy crawl qiYunProxy_spider -s JOBDIR=../../crawls/qiYunProxy'.split())

云代理(yunProxy.py)

import datetime
import timeimport scrapy
from scrapy.cmdline import executefrom douban.items import ProxyItemclass YunproxySpider(scrapy.Spider):name = 'yunProxy'allowed_domains = ['www.ip3366.net']start_urls = ['http://www.ip3366.net/']next_page = 1def parse(self, response):tr_list = response.css("div#list>table>tbody tr")for tr in tr_list:ip = tr.css("td:nth-child(1)::text").get()port = tr.css("td:nth-child(2)::text").get()schema = tr.css("td:nth-child(4)::text").get()if schema.lower() == "http" or schema.lower() == "https":item = ProxyItem()item['schema'] = schema.strip().lower()item['ip'] = ip.strip()item['port'] = port.strip()item['original'] = '云代理'item['created_time'] = time.strftime('%Y-%m-%d', time.localtime(time.time()))if item._check_format():yield itemself.next_page += 1# int 类型不能直接和字符串拼接next_page = "?stype=1&page=" + str(self.next_page)if self.next_page != 2:next_url = 'http://www.ip3366.net/' + next_pageyield scrapy.Request(next_url, dont_filter=True)if __name__ == '__main__':execute(['scrapy', 'crawl', 'yunProxy'])# execute('scrapy crawl yunProxy_spider -s JOBDIR=../../crawls/yunProxy'.split())

将获取到的免费代理 ip 存入 redis 数据库

import redisclass ProxyPoolPipeline(object):REDIS_HOST = '127.0.0.1'REDIS_PORT = 6379REDIS_PARAMS = ''server = redis.StrictRedis(host=REDIS_HOST, port=REDIS_PORT, password=REDIS_PARAMS)# 保存未检验代理的 Redis keyPROXIES_UNCHECKED_LIST = 'proxies:unchecked:list'# 已经存在的未检验 HTTP 代理和 HTTPS 代理集合PROXIES_UNCHECKED_SET = 'proxies:unchecked:set'# 将可用的IP代理添加到代理池队列def process_item(self, item, spider):if not self._is_existed(item):# 用于其它爬虫判断 ip 是否被封禁等,删除 redis 内的代理self.server.hincrby("proxies:unchecked:set_stats", item._get_url(), 1)# rpush 命令用于将一个或多个值插入到列表的尾部# self.server.rpush(self.PROXIES_UNCHECKED_LIST, json.dumps(dict(item), ensure_ascii=False))# 检查 IP 代理是否已经存在def _is_existed(self, item):# 以集合的方式插入, sadd 命令将一个或多个成员元素加入到集合中,已经存在于集合的成员元素将被忽略added = self.server.sadd(self.PROXIES_UNCHECKED_SET, item._get_url())# added = self.server.rpush(self.PROXIES_UNCHECKED_SET, item._get_url())return added == 0

付费代理 ip (ipProxy.py)

# 获取花钱买的代理
import timeimport redis
import requestsurl = ""
while True:r = requests.get(url)# 亲测站大爷和代理云经过下面的处理后,存入 redis 的数据格式变为 58.243.143.247:57114text = r.text# 去除字符串首位的回车换行符,不然后面的 text 会多出一个空字符(由 replace 和 split 联合产生)text = text.strip()# 去除字符串中间的回车换行符text = [text.replace('\r\n', ',')]# 这里不能写成 text = [x.split(",") for x in text] ,不然会出现[['58.243.143.247:57114', '58.243.143.247',...]]for x in text:text = x.split(",")server = redis.StrictRedis(host='127.0.0.1', port=6379, password='')length = 0for i in range(len(text)):item = "http://" + text[i]added = server.sadd('proxies:unchecked:set', item)if added != 0:server.hincrby("proxies:unchecked:set_stats", item, 1)length += 1passpass# can only concatenate str (not "int") to strprint("本次获得 " + str(length) + " 个 ip")# 睡眠 10 分钟,再次获取 iptime.sleep(600)

2、 从 redis 数据库中随机取出一个代理 ip 用作这次请求的代理

# 随机选择 IP 代理下载器中间件
class RandomProxyMiddleware(object):# 第 2 爬虫开启前就执行def __init__(self, settings):# 2.初始化配置及相关变量self.r = redis.Redis(host='127.0.0.1')self.proxy_key = "proxies:unchecked:set"self.proxy_stats_key = self.proxy_key + '_stats'# 最多失败 1 次self.max_failed = 2@propertydef proxies(self):# self.r.lrange(self.proxy_key, 0, -1) 对列表数据进行读取操作return [i.decode('utf-8') for i in self.r.smembers(self.proxy_key)]# 最先执行,爬虫开启前就执行# 这个函数是访问 setting 和 signals 的入口,比如读取 settings.py 的某些配置。重写这个方法需要返回实例对象;如果返回对象里有参数,可在初始化方法 __init__()@classmethoddef from_crawler(cls, crawler):# 1. 创建中间件对象# 默认代理是启用的if not crawler.settings.getbool('HTTPPROXY_ENABLED'):raise NotConfiguredreturn cls(crawler.settings)def process_request(self, request, spider):# 3. 为每个 request 对象分配随机的 ip 代理if self.proxies and not request.meta.get('proxy') and request.url not in spider.start_urls:request.meta['proxy'] = random.choices(self.proxies)# 因为 random.choices(self.proxies) 出来的是 list 数据类型:['http://124.93.201.59:42672']# 报错:TypeError: expected string or bytes-like objectrequest.meta['proxy'] = request.meta['proxy'][0]# 花钱买的代理需要验证,无这个验证报错 407# 设置代理的认证信息(站大爷可以自动绑定 ip,可以不用设置账号密码验证)# auth = base64.b64encode(bytes("username:password", 'utf-8'))# request.headers['Proxy-Authorization'] = b'Basic ' + authdef process_response(self, request, response, spider):# 4.0 请求成功cur_proxy = request.meta.get('proxy')# redis升级到3.0后仅接受用户数据为字节、字符串或数字(整数,长整数和浮点数)# 将键或值指定为任何其他类型将引发DataError异常# redis.exceptions.DataError: Invalid input of type: 'NoneType'. Convert to a bytes, string, int or float first.# cur_proxy 为 NoneType 类型,None# 判断 ip 是否被对方封禁if response.status in (401, 403, 400, 307, 302, 503):self.r.hincrby(self.proxy_stats_key, cur_proxy, 1)# 当某个 IP 的失败次数累积到一定的数量filed_times = self.r.hget(self.proxy_stats_key, cur_proxy) or 0if int(filed_times) >= self.max_failed:print('got wrong http code (%s) when use %s' % (response.status, cur_proxy))# 可以认为该 IP 被对方封禁。从代理池中将该 IP 删除self.remove_proxy(cur_proxy)del request.meta['proxy']# 返回 request 将该请求重新->调度器return request# # 访问没达到效果的状态码(302 豆瓣:有异常 ip 从你这里发出)# elif response.status in (302, 503):#     return requestreturn responsedef process_exception(self, request, exception, spider):# 4.1 请求失败cur_proxy = request.meta.get('proxy')# 请求使用代理,并且网络请求报错,认为该 IP 出错,删除,并重新->调度器# 判断 cur_proxy 的类型是否在元组中,是返回 True ,不在元组中返回 false# isinstance(cur_proxy, (ConnectError, TimeoutError)) 本身就是错误,只会判断结果只会出现 falseif cur_proxy and isinstance(exception, (ConnectError, TimeoutError)):print('error (%s) occur when use proxy %s' % (exception, cur_proxy))self.remove_proxy(cur_proxy)del request.meta['proxy']return requestdef remove_proxy(self, proxy):if proxy in self.proxies:# lrem 根据参数 COUNT 的值,移除列表中与参数 VALUE 相等的元素# count > 0 : 从表头开始向表尾搜索,移除与 VALUE 相等的元素,数量为 COUNT# count < 0 : 从表尾开始向表头搜索,移除与 VALUE 相等的元素,数量为 COUNT 的绝对值# count = 0 : 移除表中所有与 VALUE 相等的值# self.r.lrem(self.proxy_key, proxy) 列表操作self.r.srem(self.proxy_key, proxy)self.r.hdel(self.proxy_stats_key, proxy)

3、 在 settings.py 中开启代理 ip

注: 使用下面的 DOWNLOADER_MIDDLEWARES 再次将 settings.py 中的 DOWNLOADER_MIDDLEWARES 进行覆盖

DOWNLOADER_MIDDLEWARES = {'douban.middlewares.RandomProxyMiddleware': 543,'scrapy.contrib.downloadermiddleware.useragent.UserAgentMiddleware': None,'douban.useragent.RotateUserAgentMiddleware': 400,
}

在 settings.py 内追加 redis 的相关配置(缺陷:无论启动那一只蜘蛛都要在启动之前开启 redis 服务,解决:第八点中的 custom_settings)

# 调度器启用 Redis 存储 Requests 队列
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 确保所有的爬虫实例使用 Redis 进行重复过滤
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 将 Requests 队列持久化到 Redis ,可支持暂停或重启爬虫
SCHEDULER_PERSIST = True
# Requests 的调度策略,默认优先级队列
SCHEDULER_QUEUE_CLASS = 'scrapy_redis.queue.PriorityQueue'

4、 扩展

1、 获取来的代理 ip 存在一定的质量问题,不是所有的 ip 都可用(中间件上设置了某个 ip 访问失败达一定次数后从 redis 数据库内删除)
2、 确定某个 ip 是否能与主机连上的时间间隔过长(3分钟),在 settings.py 中追加以下代码:

# TCP connection time out (还有下载超时,默认180)
DOWNLOAD_TIMEOUT = 60

3、 代理 ip 获取的数据少于真实数据的个数,在 settings.py 中解开下面代码的注释:

AUTOTHROTTLE_ENABLED = True

4、 让蜘蛛访问网站更像人正在访问该网站可以为每次访问设置时间间隔,在 settings.py 中解开和追加代码:

# 单位时间内的点击次数,这个是很多网站都会有的反爬虫措施(延时1秒,不能动态改变,导致访问延时都差不多,也容易被发现)
DOWNLOAD_DELAY = 30
# 启用后,当从相同的网站获取数据时, Scrapy 将会等待一个随机的值,延迟时间为0.5到1.5之间的一个随机值乘以 DOWNLOAD_DELAY
RANDOMIZE_DOWNLOAD_DELAY = True

5、 动态的为 Scrapy 添加 start_urls (未使用到所以未检验):

经过测试 在 Scrapy 的主要抓取文件里面,添加  start_requests 方法,这是 Scrapy 提供的方法哦, 在内部直接执行 yield Request(newUrl)  就可以发起新的抓包请求。 同时需要注意的是,如果写了 复写 start_requests 方法,start_urls 的请求就失效了。来给你一个范例:
class AAA(Spider):name = "AAA"start_urls = ["http://www.xxx.com/handbook/201710/xxx.html",]def __init__(self):super(AAA, self).__init__()def start_requests(self):params = {'pageCount': '100'}content = requests.get('http://AAA.cc/AAA/json', params)json = content.json()resultJson = json["result"]for result in resultJson:newUrl = result["AAAUrl"]print("当前抓取的 Url 是:" + newUrl)yield Request(newUrl)def parse(self, response):content = response.body.decode("utf-8")print(content)作者:知乎用户
链接:https://www.zhihu.com/question/50462759/answer/246929608
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

八、多管道、多蜘蛛

1、 每一个 spider 需要的配置可能不一样

在 spider 内使用 custom_settings 对 settings.py 中的相应的文件内容进行覆盖,例如在快代理(kuaiProxy.py)中使用:name = 'kuaiProxy'allowed_domains = ['www.kuaidaili.com']start_urls = ['https://www.kuaidaili.com/free/inha/']custom_settings = {'DOWNLOAD_DELAY': 1,'ROBOTSTXT_OBEY': True,'ITEM_PIPELINES': {'douban.pipelines2redis.ProxyPoolPipeline': 308},}

2、 在 douban 文件夹下创建 crawls 文件夹并在该文件夹内创建 crawls.py 文件统一启动所有蜘蛛

# 执行所有爬虫
import multiprocessing
import osfrom scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings# class StartSpider:
#     # 异步执行
#     def start_by_process(self):
#         process = CrawlerProcess(get_project_settings())
#         # 爬代理
#         process.crawl('kuaiProxy')
#         process.crawl('qiYunProxy')
#         process.crawl('yunProxy')
#         # 爬内容
#         process.crawl('movieInfo')
#         process.crawl('comment')
#
#         process.start()
#
#     # 顺序执行
#     def start_by_os(self):
#         # 深入文件夹,运行文件
#         os.system("cd comment && cd spiders && scrapy runspider kuaiProxy.py && scrapy runspider "
#                   "qiYunProxy.py && scrapy runspider yunProxy.py")
#         os.system("cd comment && cd spiders && scrapy runspider movieInfo.py && scrapy runspider "
#                   "comment.py")
#
#     # 先同步后异步:先爬取代理后,依靠代理爬数据
#     # 方法一:再建2个 py 文件,两个文件内异步进行,最外的同步进行(未检测是否可行)
#
#
# startSpider = StartSpider()
# startSpider.start_by_process()
# startSpider.start_by_os()# 方法二:有上面的代码,不需要下面区域内的代码===================================================================================
def start_by_pool(item):if item != "ipProxy":os.system("cd .. && cd douban && cd spiders && scrapy runspider " + item + ".py")else:os.system("cd .. && cd douban && python " + item + ".py")if __name__ == "__main__":# 这里设置允许同时运行的的进程数量要考虑机器 cpu 的数量,进程的数量最好别大于 cpu 的数量,# 因为即使大于 cpu 的数量,增加了任务调度的时间,效率反而不能有效提高# redis.exceptions.TimeoutError: Timeout reading from socketpool = multiprocessing.Pool(processes=2)item_list = ['qiYunProxy', 'yunProxy', 'kuaiProxy', 'movieInfo', 'comment']for item in item_list:# 维持执行的进程总数为 processes ,当一个进程执行完毕后会添加新的进程进去pool.apply_async(start_by_pool, (item,))pool.close()  # 关闭进程池(pool),使其不在接受新的任务# 主进程阻塞等待子进程的退出, join 方法要在 close 或 terminate 之后使用# 调用 join 之前,先调用 close 函数,否则会出错。执行完 close 后不会有新的进程加入到 pool , join 函数等待所有子进程结束pool.join()
# ======================================================================================================================

九、 Scrapy 每天定时爬取数据

1、生成日志文件(控制台不输出)

在 settings.py 中追加以下代码:

# CRITICAL - 严重错误; ERROR - 一般错误; WARNING - 警告信息; INFO - 一般信息; DEBUG - 调试信息
LOG_LEVEL = 'DEBUG'
# 日志使用的编码
LOG_ENCODING = 'utf-8'
# 日志命名
LOG_FILE = f"log" + datetime.datetime.now().strftime('%Y%m%d') + ".txt"

2、启动 spiders 的 startSpidersDaily.py 文件

# 文件timerStartDaily.py
from scrapy import cmdline
import datetime
import time
import shutil
import osrecoderDir = r"crawls"  # 这是为了爬虫能够续爬而创建的目录,存储续爬需要的数据
checkFile = "isRunning.txt"  # 爬虫是否在运行的标志startTime = datetime.datetime.now()
print(f"startTime = {startTime}")miniter = 0
while True:isRunning = os.path.isfile(checkFile)# 爬虫不在执行状态则开始启动爬虫if not isRunning:# 在爬虫启动之前处理一些事情,清掉 JOBDIR = crawlsisExsit = os.path.isdir(recoderDir)  # 检查 JOBDIR 目录 crawls 是否存在print(f"Spiders not running, ready to start. {recoderDir} isExsit:{isExsit}")if isExsit:shutil.rmtree(recoderDir)print(f"At time:{datetime.datetime.now()}, delete res:{recoderDir}")else:print(f"At time:{datetime.datetime.now()}, Dir:{recoderDir} is not exsit.")# # execute 只执行第一个# # 在爬虫运行过程中,会自动将状态信息存储在 crawls/comment_spider 目录下,支持续爬# # 若想支持续爬,在 ctrl+c 终止爬虫时,只能按一次,爬虫在终止时需要进行善后工作,切勿连续多次按 ctrl+c# cmdline.execute('scrapy crawl kuaiProxy_spider -s JOBDIR=crawl/kuaiProxy_spider'.split())# cmdline.execute('scrapy crawl qiYunProxy_spider -s JOBDIR=crawl/qiYunProxy_spider'.split())# cmdline.execute('scrapy crawl yunProxy_spider -s JOBDIR=crawl/yunProxy_spider'.split())# cmdline.execute('scrapy crawl movieInfo_spider -s JOBDIR=crawl/movieInfo_spider'.split())# cmdline.execute('scrapy crawl comment_spider -s JOBDIR=crawl/comment_spider'.split())# os.system("cd .. && cd comment && python ipProxy.py")os.system("python crawls.py")# 爬虫结束之后,退出脚本breakelse:print(f"At time:{datetime.datetime.now()}, spiders is running, sleep to wait.")# 每10分钟检查一次time.sleep(600)miniter += 10# 等待满24小时,自动退出监控脚本if miniter >= 1440:break

3、 系统启动 startSpidersDaily.py 的 bat 文件

cd /d D:\workplace\python\douban\crawls
call python startSpidersDaily.py
pause

4、 设置每天的定时任务(我是 window10)

1、 打开计算机管理

2、 创建基本任务

3、触发器选择每天

4、一直下一步,直到启动程序

5、 创建完后需要修改

在右边找到自己创建时对应的名称后双击

十、我的资源包

Scrapy 框架爬取豆瓣电影的信息(包括图片)和电影评论-3

Scrapy 框架爬取豆瓣电影的信息(包括图片)和电影评论-1

十一、参考

python实现scrapy爬虫每天定时抓取数据
scrapy-redis ip代理池
mongo操作图片储存

scrapy框架中多个spider,tiems,pipelines的使用及运行方法

Scrapy 框架爬取豆瓣电影的信息(包括图片)和电影评论-2相关推荐

  1. 基于Scrapy框架爬取豆瓣《复联4》影评,并生成词云

    基于Scrapy框架爬取豆瓣<复联4>影评,并生成词云 1. 介绍及开发环境 2. 爬虫实现 2.1 新建项目 2.2 构造请求 2.3 提取信息 2.4 数据存储 2.4 运行结果 3. ...

  2. Scrapy 框架获取豆瓣电影的信息(包括图片)和电影评论-1

    文章目录 一.项目目录 二.定义爬取结果存储的数据结构(items.py) 电影信息 评论信息 三.爬取到结果后的处理类(spiders 文件夹) 电影信息(movieInfo.py) 评论信息(co ...

  3. 利用Scrapy框架爬取前途无忧招聘信息

    利用Scrapy框架爬取前途无忧招聘信息 关于安装和命令使用可参考:https://docs.scrapy.org/en/1.7/intro/install.html 先创建项目和爬虫文件 分析网站 ...

  4. 用Scrapy框架爬取豆瓣电影,构建豆瓣电影预测评分模型

    文章目录 前言 一.Scrapy爬虫爬取豆瓣电影 1. Scrapy框架介绍 (1) Scrapy框架构造: (2) 数据流 (3) 项目结构 2. 创建爬虫爬取豆瓣 (1)创建项目 (2) 创建It ...

  5. 03_使用scrapy框架爬取豆瓣电影TOP250

    前言: 本次项目是使用scrapy框架,爬取豆瓣电影TOP250的相关信息.其中涉及到代理IP,随机UA代理,最后将得到的数据保存到mongoDB中.本次爬取的内容实则不难.主要是熟悉scrapy相关 ...

  6. 爬虫项目实操三、用scrapy框架爬取豆瓣读书Top250的书名,出版信息和评分

    安装方法:Windows:在终端输入命令:pip install scrapy:mac:在终端输入命令:pip3 install scrapy,按下enter键,再输入cd Python,就能跳转到P ...

  7. python scrapy框架爬取知乎提问信息

    前文介绍了python的scrapy爬虫框架和登录知乎的方法. 这里介绍如何爬取知乎的问题信息,并保存到mysql数据库中. 首先,看一下我要爬取哪些内容: 如下图所示,我要爬取一个问题的6个信息: ...

  8. python scrapy框架爬取豆瓣top250电影篇一Windows下建立Scrapy项目,pycharm编辑

    1.打开cmd,进入到项目准备所放在的文件夹,执行命令: scrapy startproject douban 然后就可以使用pycharm打开项目了 2.建立spider文件 cmd命令行进入到项目 ...

  9. 使用scrapy框架爬取豆瓣影评

    2019独角兽企业重金招聘Python工程师标准>>> 最近几天在看平凡岁月 感觉挺不错的一部生活剧,想看看豆瓣 对该据评论,使用scrapy爬取,基于python2.7进行实现 1 ...

  10. Python爬虫实战+Scrapy框架 爬取当当网图书信息

    1.环境准备 1.在python虚拟环境终端使用 pip install scrapy下载scrapy依赖库 2.使用scrapy startproject book创建scrapy心目工程 3.使用 ...

最新文章

  1. html权重值_HTML标签权重分值排列
  2. python3与python2的编码问题
  3. mysql-connector-net-6.7.4.msi,在ActiveReports中使用MySQL数据库
  4. 一款功能齐全的网管软件:Ip-tools
  5. js调用java代码返回解决方案
  6. Launch debug in SWI1 workflow
  7. Java 集合系列(一)
  8. python io_NumPy IO
  9. input获得焦点和失去焦点
  10. 设置 NSZombieEnabled 定位 EXC_BAD_ACCESS 错误
  11. 基于JAVA+SpringMVC+Mybatis+MYSQL的图书租赁系统
  12. 计算机网络基础知识 帮助学习网络管理的初学者快速了解网络管理的初步结构知识...
  13. 【学习笔记】深入理解Linux内核第三版 ——第二章 内存寻址
  14. 梦幻西游五虎将访谈系列:主策划小白
  15. QT连接MySQL数据库问题
  16. 无法访问此网站 localhost 拒绝了我们的连接请求
  17. vue element 的el-checkbox-group默认全部选中
  18. Access 的 AutoExec 宏
  19. h5在ios系统里调用微信jsdk失败
  20. 「小程序JAVA实战」微信小程序简介(一)

热门文章

  1. linux运行qt designer,用快速开发工具Qt Designer编写Qt程序
  2. m1芯片xcode打包IPA processing failed错误解决方案
  3. 软件项目版本管理规范总结
  4. 解决This application failed to start because no Qt platform plugin could be initialized的问题
  5. 80核处理器_【装机帮扶站】第338期:95元的6核心12线程处理器
  6. esxi 部署模板_vSphere通过模板批量部署虚拟机
  7. 微信小程序SEO排名优化
  8. 微信小程序 实现简单倒计时功能
  9. 电路串联和并联图解_迷惑我们很久的串联/并联谐振电路(多图、详解)
  10. ANSYS 2020R2 workbench汉化的方法