Scrapy爬取小说简单逻辑
一 准备工作
1)安装Python
2)安装PIP
3)安装scrapy
4)安装pywin32
5)安装VCForPython27.exe
...........
具体安装步骤,可参考http://www.cnblogs.com/zyj-python/p/7392476.html
二 爬虫逻辑
1.CMD终端创建爬虫项目
cd Desktop(返回桌面目录) #选择文件保存位置,我放在了桌面Scrapy startProject BooksSpider #BooksSpider为项目名称,自己起名 (ps:CMD终端显示"rou can start your first spider with:"表示项目创建成功)
2.创建爬虫文件
拖动爬虫项目文件用Pycharm打开,点击左下角Terminal打开终端
scrapy genspider books(蜘蛛名,自定义,不能重复,可以修改但不建议修改) www.qisuu.com(网站域名, 这里以奇书网为例)
3.双击打开爬虫文件(蜘蛛文件.py),在Spiders包中引用可能用到的包
import sysreload(sys)sys.setdefaultencoding("utf-8")import scrapyimport urlparsefrom ..items import BooksItem
(ps:文件夹图标中带空心圆为包,只有包才能直接引入,带__init__.py的文件,
没有则表示文件夹)
以下是创建爬虫文件自带:
class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['www.qisuu.com'] start_urls = ['http://www.qisuu.com/'] def parse(self, response): pass
4.明确爬取目标
以奇书网为例:
1)请求导航条上每个按钮对应页面
2)分别解析每个页面的电子书列表(主要获得电子书详情URL)
3)请求详情URL,解析电子书的详细信息(书名,封面,评分,大小....下载地址)
4)根据下载地址下载电子书到本地
制作爬虫:
在books.py中
# -*- coding: utf-8 -*-import sysreload(sys)sys.setdefaultencoding("utf-8")import scrapyimport urlparsefrom ..items import BooksItem class BooksSpider(scrapy.Spider): name = 'books' allowed_domains = ['www.qisuu.com'] start_urls = ['http://www.qisuu.com/'] #获取首页导航条的url def parse(self, response): a_list=response.xpath("//div[@class='nav']/a[@target='_blank']") for a in a_list: #分类名称 category_namme=a.xpath("text()").extract_first("") #拼接完整的分类url category_url=urlparse.urljoin(response.url,a.xpath("@href").extract_first("")) #yield将结果返回调度器 #将分类地址转发给downloader下载并将结果传给parse_books_list #meta:专门用来传递参数,类型是字典 yield scrapy.Request( url=category_url, callback=self.parse_books_list, meta={ "category_namme":category_namme,} ) #获取分类页面的所有url def parse_books_list(self,response): href_list=response.xpath("//div[@class='listBox']/ul/li/a/@href").extract() for href in href_list: list_href=urlparse.urljoin(response.url,href) yield scrapy.Request( url=list_href, callback=self.parse_books_detail, meta=response.meta, # meta={ "category_namme": response.meta['category_namme'],} ) #获取所有页数,并循环获得每一页的url all_pages=response.xpath("//select[@name='select']/option/@value").extract() for page in all_pages: detail_url=urlparse.urljoin(response.url,page) yield scrapy.Request( url=detail_url, callback=self.parse_books_list, meta=response.meta ) #获取每个小说的详情 def parse_books_detail(self,response): info_div=response.xpath("//div[@class='detail_right']") title=info_div.xpath("h1/text()").extract_first("") li_list=info_div.xpath("ul/li") size=li_list[2].xpath("text()").extract_first("") size=size.replace(u"文件大小:","").strip() date_time=li_list[4].xpath("text()").extract_first("") date_time=date_time.replace(u"发布日期:","").strip() user=li_list[6].xpath("a/text()").extract_first("") download_times=li_list[1].xpath("text()").extract_first("") download_times = download_times.replace(u"下载次数:", "").strip() book_degree=li_list[7].xpath("em/@class").extract_first("") book_degree = book_degree.replace("lstar","").strip() download_url=response.xpath("//a[@class='downButton']/@href")[1].extract() img_url=response.xpath("//div[@class='detail_pic']/img/@src").extract_first("") img_url=urlparse.urljoin(response.url,img_url) category_namme=response.meta['category_namme'] print title,user,date_time,category_namme item=BooksItem() item['title']=title item['size']=size item['date_time']=date_time item['user']=user item['download_times']=download_times item['book_degree']=book_degree item['download_url'] = [u"%s"%download_url] #当下在路径有乱码,加u 小说要以GBK格式存储,有中文时要进行编码 item['img_url']=[img_url] item['category_namme']=category_namme yield item #yield 将结果返回给items.py文件
代码中的xpath与正则表达式是一样的,只是用法更加简单方便, 具体操作可百度, 此处不细说.
在items.py文件中
# -*- coding: utf-8 -*-# Define here the models for your scraped items## See documentation in:# http://doc.scrapy.org/en/latest/topics/items.htmlimport scrapyclass BooksspiderItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() # pass class BooksItem(scrapy.Item): title = scrapy.Field() size = scrapy.Field() date_time = scrapy.Field() user = scrapy.Field() download_times = scrapy.Field() book_degree = scrapy.Field() download_url = scrapy.Field() img_url = scrapy.Field() category_namme = scrapy.Field() #自定义一个类,用来接收获取到的数据 #Field()可以接受任何类型的参数
这时就可以开始爬虫了, 代码为:
scrapy crawl books -o book.json -s FEED_EXPORT_ENCODING = utf-8
其中 scrapy crawl books 是运行books爬虫程序, -o book.json 为以json格式保存, FEED_EXPORT_ENCODING = utf-8 为编码格式
友情提示: 不要轻易去爬虫,只有确定自己代码没有问题才可以,可以先使用终端测试(cmd),将代码一行一行依次粘贴运行
scrapy shell http://www.qisuu.com
(ps:利用CMD终端测试,不要轻易去爬虫,成功末尾显示IN[1],然后依次在终端复制粘贴进去
相关代码,包括相关引入import代码,利用xpath取特定数据可在终端打印查看效果,有时要回
车两次展示,在目标网站没有反爬虫协议或所需数据极少时可考虑在Terminal直接运行)
如果想要下载至本地:
需要修改settings.py文件
ITEM_PIPELINES = { # 'BooksSpider.pipelines.BooksspiderPipeline': 300, "scrapy.pipelines.images.ImagesPipeline":1, "scrapy.pipelines.files.FilesPipeline":2,}IMAGES_URLS_FIELD = "img_url"IMAGES_STORE = "imgs"FILES_URLS_FIELD = "download_url"FILES_STORE = "files"
可能存在的问题,原因及解决方案:
1.网站源代码结构与请求到的代码结构可能不一致
(如tbody只在浏览器渲染的结构中有而请求出来的没有)
解决方案:优化xpath写法,或改用正则表达式
2.请求robots.txt后显示200意为请求到反爬虫协议成功会自动停止爬虫程序
解决方案:设置不遵守robots.txt反爬虫协议,强行进入
3.在请求到某个url显示200成功后却突然自动停止爬虫(closing spider)
可能原因:若显示Filtered offsite request则意为scrapy自动过滤该url把它放入了黑名单
解决方案:在该url代码运行的函数meta字典中加入dont_filter = True默认
True不要过滤,若改为False则是要过滤
以上就是Scrapy爬虫的基本逻辑!