from itemadapter import ItemAdapter import json #字典 from demo_58.items import Demo58Item_ershou,Demo58Item_zufang #redis指纹服务,数据保存,数据对比 from demo_58.ext_mod import Filter #实例化对象 fu = Filter() class Demo58Pipeline_zufang: def __init__(self): #文件打开 self.file = open('租房信息.json','a') def process_item(self, item, spider): # 判断选择目标数据 --》item.py文件的对应类对象 if isinstance(item,Demo58Item_zufang): data = dict(item) tit = data['title'] # 将标题处理成密文 # 判断这个tit不存在的时候 if not fu.isismember(tit): # 不存在就添加 fu.add_data(tit) self.file.write(json.dumps(data,ensure_ascii=False)+',\n') return item def __del__(self): self.file.close() # 保存二手房信息 class Demo58Pipeline_ershoufang: def __init__(self): self.file = open('二手房信息.json', 'a') def process_item(self, item, spider): if isinstance(item, Demo58Item_ershou): data = dict(item) tit = data['title'] # 将标题处理成密文 # 判断这个tit不存在的时候 if not fu.isismember(tit): # 不存在就添加 fu.add_data(tit) self.file.write(json.dumps(data, ensure_ascii=False) + ',\n') return item def __del__(self): self.file.close()
import redis # pip install redis import hashlib redis_host = '127.0.0.1' class Filter(object): '''将目标数据处理成哈希密文 用密文值比对更快''' def get_md5(self,val): md5 = hashlib.md5() # update()接受待加密对象 md5.update(val.encode('utf-8')) return md5.hexdigest() #取出密文值 '''将密文添加到队列''' def add_data(self,url): # Python与redis建立链接 red = redis.Redis(host=redis_host,port=6379,db=1) reslut = red.sadd('tc58:set_data',self.get_md5(url)) if reslut == 0: return False else: return True '''判断是否存在在集合中''' def isismember(self,url): # Python与redis建立链接 red = redis.Redis(host=redis_host, port=6379, db=1) # sismember()判断某内容存在 res = red.sismember('tc58:set_data',self.get_md5(url)) return res
import scrapy from demo_58.items import Demo58Item_zufang,Demo58Item_ershou # 1.导入RedisSpider类 from scrapy_redis.spiders import RedisSpider # 2,继承类 class SpiderSpider(RedisSpider): name = 'spider' # 3.注释域名和起始URL,不做使用 # allowed_domains = ['58.com'] # start_urls = ['http://58.com/'] # 4 设置redis_key redis_key = 'spider:start_url' def parse(self, response):
解析,保存为字典
yield 字典
#启动
if __name__ == '__main__': from scrapy import cmdline cmdline.execute(['scrapy', 'crawl', 'spider'])
随机ua
class UserAgentDownloadMiddleware: user_agent = [ 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/14.0.835.163 Safari/535.1', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50', 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:77.0) Gecko/20190101 Firefox/77.0', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36', 'Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16.2' ] # 方法名是scrapy规定的方法 (协商机制) # 每个交给下载器的request对象都会经过该方法,并期望返回response def process_request(self, request, spider): # 获取随机请求头 u_a = random.choice(self.user_agent) # 设置请求头 request.headers['User-Agent'] = u_a 随机ip class RandomProxy: ip_list = [ '124.116.116.13:4228', '122.194.194.139:4212', '36.42.248.45:4215', '1.83.250.183:4228', '49.85.43.175:4223', '121.205.229.70:4231', ] def process_request(self, request, spider): proxy = random.choice(self.ip_list) # 修改请求的元数据字典 # 如果是将IP以列表随机形式构造 需要加上https://,否则报错 request.meta['proxy'] = 'https://' + proxy # 如果是将IP以字典形式构造 print('IP:', request.meta)
分布式爬取数据
分布式处理数据
断点续爬
启动从机#可启动多个,尽量别超过8个,否则电脑容易出问题
#爬虫文件上一级目录下
scrapy runspider 爬虫文件.后缀
启动主机
redis-cli
任务发布
#@1为spider中redis_key
lpush @1 网址
如错误欢迎指出,本人也小白,希望尽微薄之力让更多人理解