Scrapy入门笔记(测试download图片)
环境搭建:
关于这一点,在Windows环境下,请务必使用 Anaconda 这个Python的发行版本,不然光环境的各种报错就能消磨掉你所有的学习兴趣!
参考文档:http://blog.csdn.net/u014175572/article/details/54427525
下面通过download图片的实例来展示Scrapy的基本功能。
使用Scrapy第一步:创建项目;CMD进入你需要放置项目的目录 输入:
scrapy startproject XXXXX XXXXX代表你项目的名字
例如我在工作路径下输入:
scrapy startproject mmjpg
创建成功就会显示:
New Scrapy project 'mmjpg', using template directory 'D:\\Anaconda3\\lib\\site-packages\\scrapy\\templates\\project', created in:
E:\pythonworkspace\mmjpg
You can start your first spider with:
cd mmjpg
scrapy genspider example example.com
用PyCharm工具打开,显示的目录结构如下:
一个小技巧,Scrapy默认是不能在IDE中调试的,我们在根目录中新建一个py文件叫:entrypoint.py;在里面写入以下内容:
from scrapy.cmdline import execute execute(['scrapy', 'crawl', 'mmjpg'])
注意!第二行中代码中的前两个参数是不变的,第三个参数请使用自己的spider的名字。稍后我会讲到!!
建立一个项目之后:
第一件事情是在items.py文件中定义一些字段,这些字段用来临时存储你需要保存的数据。方便后面保存数据到其他地方,比如数据库 或者 本地文本之类的。
第二件事情在spiders文件夹中编写自己的爬虫
第三件事情在pipelines.py中存储自己的数据
还有一件事情,不是非做不可的,就settings.py文件 并不是一定要编辑的,只有有需要的时候才会编辑。
第一步定义字段:
在items.py这个文件中
就像下面这样:
# -*- coding: utf-8 -*- # Define here the models for your scraped items # # See documentation in: # http://doc.scrapy.org/en/latest/topics/items.html import scrapy class MmjpgItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # 图片集合名称 title = scrapy.Field() # 图片序号 picIndex = scrapy.Field() # 图片路径 src_info = scrapy.Field() # 文件夹路径 dirPath = scrapy.Field()
第二步编写Spider:
在spiders文件中新建一个mmjpg.py文件,结构如下:
具体的网页节点分析,提取省略,最终的代码如下:
# coding:utf-8 import time import os import re import shutil import scrapy # 导入scrapy包 from bs4 import BeautifulSoup from scrapy.http import Request ##一个单独的request的模块,需要跟进URL的时候,需要用它 from mmjpg.items import MmjpgItem class Myspider(scrapy.Spider): name = 'mmjpg' # allowed_domains = ['23wx.com'] bash_url = 'http://www.mmjpg.com/' # bashurl = '.html' dir_path = 'G:\mmjpg' # 图片存放的路径 def start_requests(self): yield Request(self.bash_url, self.parse) # 1、获取总页数,并且遍历每一张列表页面页。 def parse(self, response): # print(response.text) Soup = BeautifulSoup(response.text, 'lxml') page_div = Soup.find('div', class_='page').find('a',class_='last'); # print(page_div); all_page_info = page_div['href']; # 获取到总页数 all_page_number = all_page_info.split('/')[2]; second_url = all_page_info.split('/')[1]; for x in range(1, int(all_page_number) + 1): # http://www.mmjpg.com/home/2 if x == 1: list_page = self.bash_url else: list_page = self.bash_url + second_url + '/' + str(x) # print(list_page) # self.getListInfo(list_page) yield Request(list_page, self.getListInfo) # print('遍历每一张列表页面页,休息2秒钟再继续......') # print('*' * 60) # time.sleep(2) # 2、获取每一张列表页面页里面的列表信息(标题+url)。 def getListInfo(self, response): # print(response.url) list_info_html = response.text list_info_soup = BeautifulSoup(list_info_html, 'lxml') list_dd = list_info_soup.find('div', class_='pic').find_all('span', class_='title'); for a in list_dd: # print(a['href']) item = a.find('a') title = item.get_text() # 取出a标签的文本 href = item['href'] # 取出a标签的href 属性 # print(title, href) os.chdir(self.dir_path) # if self.mkdir(title): self.mkdir(title) # os.chdir(self.dir_path + '\\' + title) # print('进入[', title, ']文件夹......') # self.getContentInfo(href, title) yield Request(href, self.getContentInfo, meta={'dirPath': self.dir_path + '\\' + title}) # time.sleep(2) # self.getContentInfo(href, title) # 3、获取每一个具体人物图片信息 def getContentInfo(self, response): # os.chdir(self.dir_path + '\\' + title) # print('进入[', title, ']文件夹......休息2秒钟......') # time.sleep(2) dirPath = response.meta['dirPath'] content_info_html = response.text content_info_soup = BeautifulSoup(content_info_html, 'lxml') page_dd = content_info_soup.find('div', class_='page').find_all('a')[-2] # print(page_dd.get_text().split('共')[1].split('页')[0]) # 获取总的图片页数 all_pic_page = page_dd.get_text(); print('共有图片【', all_pic_page, '】张。') # print(all_pic_page) # 拼接详情url # http://www.mmjpg.com/mm/854/42 pic_url_fragment = response.url # print(pic_url_fragment) for x in range(1, int(all_pic_page) + 1): # print('-----',x); if x == 1: pic_url_info = response.url else: pic_url_info = pic_url_fragment + '/' + str(x) # print(pic_url_info) # self.getImgSrc(pic_url_info, x) yield Request(pic_url_info, self.getImgSrc, meta={'index': x, 'dirPath': dirPath}) # 4、获取图片的src路径 def getImgSrc(self, response): index = response.meta['index'] dirPath = response.meta['dirPath'] # print(response.url) img_src_html = response.text img_src_soup = BeautifulSoup(img_src_html, 'lxml') # print(img_src_soup) # exit() img_label = img_src_soup.find('div', class_='content').find('img') src_info = img_label.get('src') # http://img.mmjpg.com/2015/159/3.jpg name = str(index) + '.' + src_info.split('.')[-1] # print(name) mmjpgItem = MmjpgItem() mmjpgItem['picIndex'] = name mmjpgItem['src_info'] = src_info mmjpgItem['dirPath'] = dirPath return mmjpgItem # print(src_info) # self.saveImg(name, src_info) # print(time.strftime("%Y-%m-%d %H:%M:%S")) # print('下载了一张图片[', index, '.jpg],休息0.01秒再继续。') # time.sleep(0.01) # ====================================================================================================# # 创建文件夹函数 def mkdir(self, path): path = path.strip() # temp_path = str(path.encode('utf-8')).strip() # print path # path = unicode(path, "utf-8") # os.mkdir(os.path.join('E:\pythonworkspace\meizi', path)) # os.chdir('E:\pythonworkspace\meizi\\' + path) isExists = os.path.exists(os.path.join(self.dir_path, path)) if not isExists: os.makedirs(os.path.join(self.dir_path, path)) print('建了一个名字叫做', path, '的文件夹!') # time.sleep(2) return True else: print('名字叫做[', path, ']的文件夹已经存在了!') return False
第三件事情在pipelines.py中存储自己的数据
创建一个叫processdata的文件夹,在此文件夹下添加两个python文件,__init__.py和pipelines.py
其中__init__.py文件内容为空,pipelines.py的内容如下(此文件用于保存图片):
# -*- coding: utf-8 -*- # Define your item pipelines here # # Don't forget to add your pipeline to the ITEM_PIPELINES setting # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html # from vvjob.vvjob_items import Vvjob_Item ##这是我定义的需要保存的字段,(导入dingdian项目中,items文件中的DingdianItem类) import time import traceback import requests ##导入requests import os class PmmjpgPipeline(object): def process_item(self, item, spider): name = item['picIndex'] img_url = item['src_info'] dirPath = item['dirPath'] print(name, '########', img_url, '#######', dirPath) # self.saveImg(name, img_url) os.chdir(dirPath) print('进入[', dirPath, ']文件夹......') self.saveImg(name, img_url) # with open(dirPath, 'wb') as handle: # response = requests.get(img_url, stream=True) # for block in response.iter_content(1024): # if not block: # break # # handle.write(block) print(time.strftime("%Y-%m-%d %H:%M:%S")) print('下载了一张图片[', name, '.jpg]') return item ##这个函数保存图片 def saveImg(self, name, img_url): img = self.requestImg(img_url) f = open(name, 'ab') f.write(img.content) f.close() def requestImg(self, url): ##这个函数获取网页的response 然后返回 try: img = requests.get(url, headers={ 'User-Agent': "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1" }) except Exception as e: traceback.print_exc() return self.requestImg(url) return img;
下面我们启用这个Pipeline在settings中作如下设置:
找到settings.py文件,如下图:
在此文件中找到ITEM_PIPELINES属性,打开这个注释。添加一行代码:
'mmjpg.processdata.pipelines.PmmjpgPipeline': 1,
截图如下:
PS: mmjpg(项目目录).processdata(自己建立的processdata文件夹目录).pipelines(自己建立的pipelines文件).PmmjpgPipeline(其中定义的类) 后面的 1 是优先级程度(1-1000随意设置,数值越低,组件的优先级越高)
好!我们来运行一下试试!!Go Go Go!
首先在G盘下创建一个文件夹mmjpg用来保存图片。这个路径在mmjpg.py代码中已经定义好。
打开entrypoint.py文件,按Ctrl+Shift+F10运行
此时在自定义的文件夹下图片已经在下载中: