Python日记:基于Scrapy的爬虫实现
安装 pywin32 和python版本一致
地址 https://sourceforge.net/projects/pywin32/files/pywin32/Build%20221/
安装过程中提示找不到Python2.7
解决方法:http://blog.csdn.net/pppii/article/details/48679403
安装Scrapy 使用pip
1、使用命令行创建爬虫项目
scrapy startproject myspider # cmd进入指定文件夹后创建一个名为 myspider的爬虫
2、启动pyCharm
打开项目 myspider ,在文件夹spiders下创建MySprider.py文件
添加我的爬虫 class Channel9Spider(scrapy.Spider):
name 表示爬虫的名称 属于唯一属性
allowed_domins=[] 爬虫允许的域
start_urls=[] 爬虫开始的页面
def parse(self,response): 访问地址后调用的方法
def details_parse(self,response): 处理详情页面的方法
MySprider.py遇到的问题:
1、windows命令提示符中打印爬取的文件名报错
原因:是命令行字符集和网页字符集不一致
处理方法:print item["title"].encode("gbk","ignore")
2、回调方法报错
原因:PyScrapy默认给回调加了个括号
处理方法:去掉回调方法后的括号,需要传参使用Request(url=.. , meta={'name':'yancl',....},calback=self.details_parse,dont_filter=True)
3、提示访问被拒绝
原因:1、robots 协议问题 2、由于设置了允许爬取的域
处理方法:1、修改settings.py 设置ROBOTSTXT_OBEY = True
2、调用Request方法设置dont_filter=True
打开 items.py
添加在处理页面后要传递给pipeline的item数据对象
用到了下载所以添加 file_urls,files,file_paths
打开 pipeline.py
1、添加一个继承FilesPipeline文件下载管道的实现方法 MyFilesPipeline
2、添加一个记录文件方法 JsonWithEncodingPipeline
打开settings.py
1、启用我的Item Pipeline组建。我打算下载一个视频就记录一条对应的Json信息
2、添加视频下载保存文件的路径
再次启动爬虫 scrapy crawl myspider
遇到的问题:
1、下载文件过大
2、连接超时
3、文件下载的路径问题,默认添加full的文件夹
4、文件名问题
对于问题1、2、3 修改settings
DOWNLOAD_MAXSIZE = 325674803 #字节
DOWNLOAD_WARNSIZE = 325674803 #字节
DOWNLOAD_TIMEOUT = 30 * 60 #单位秒
FILES_STORE = "F:\\mp4files" #直接使用绝对路径
对于问题3,修改MyFilesPipeline方法 重写file_path方法
再次启动爬虫运行正常,但是还有2个小问题,1、有一个文件自动添加了文件夹 2、有几个文件没有后缀大小为0KB
根据日志分析是文件名导致了 文件名中不能有:/ 等特殊字符
MySpider.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | import scrapy from mydemo.items import MydemoItem from scrapy.http import Request from scrapy.selector import Selector download_domain = "https://channel9.msdn.com" class Channel9Spider(scrapy.Spider): name = "myspider" allowed_domains = [ ".msdn.com" ] start_urls = [ "https://channel9.msdn.com/Events/Ignite/Microsoft-Ignite-China-2016?sort=status&direction=desc" ] def parse( self ,response): sale = Selector(response) for a in sale.xpath( "//h3" ): title = a.xpath( "a/text()" ).extract()[ 0 ] line = a.xpath( "a/@href" ).extract()[ 0 ] fileurl = download_domain + line yield Request(url = fileurl,meta = { 'title' :title},callback = self .details_parse,dont_filter = True ) next_page = sale.xpath( "//a[@rel='next']/@href" ).extract() if next_page: pagepath = download_domain + next_page[ 0 ] yield Request(url = pagepath,callback = self .parse,dont_filter = True ) def details_parse( self ,response): sale = Selector(response) item = MydemoItem() item[ "title" ] = response.meta[ 'title' ] fileurl = sale.xpath( "//*[@id='format']/option/@value" ).extract()[ 0 ] item[ "file_urls" ] = [fileurl] yield item |
items.py
1 2 3 4 5 6 7 8 9 10 11 | class MydemoItem(scrapy.Item): # define the fields for your item here like: # name = scrapy.Field() title = scrapy.Field() link = scrapy.Field() content = scrapy.Field() file_urls = scrapy.Field() files = scrapy.Field() file_paths = scrapy.Field() pass |
pipelines.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | # -*- 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 import scrapy import codecs import json import time from scrapy.pipelines.files import FilesPipeline from scrapy.exceptions import DropItem class MydemoPipeline( object ): def process_item( self , item, spider): return item class JsonWithEncodingPipeline( object ): def __init__( self ): self . file = codecs. open ( 'file.json' , 'w' ,encoding = 'utf-8' ) def process_item( self ,item,spider): timeSatamp = time.time() timeTuple = time.localtime(timeSatamp) curTime = time.strftime( "%Y-%m-%d %H:%M:%S" ,timeTuple) line = "[" + curTime + "] " + json.dumps( dict (item),ensure_ascii = False ) + "\n" self . file .write(line) return item def spider_closed( self ,spider): self . file .close() class MyFilesPipeline(FilesPipeline): def get_media_requests( self ,item,info): for file_url in item[ 'file_urls' ]: yield scrapy.Request(file_url,meta = { 'title' :item[ 'title' ]}) def item_completed( self , results, item, info): file_paths = [x[ 'path' ] for ok, x in results if ok] if not file_paths: raise DropItem( "Item contains no Files" ) item[ "file_paths" ] = file_paths return item def file_path( self ,request,response = None ,info = None ): title = request.meta[ 'title' ] file_guid = title + '.' + request.url.split( '/' )[ - 1 ].split( '.' )[ - 1 ] filename = u '{0}' . format (file_guid) return filename |
settings.py
生成的日志截图如下:
爬取的文件截图:
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
· 现代计算机视觉入门之:什么是视频
· 你所不知道的 C/C++ 宏知识
· 聊一聊 操作系统蓝屏 c0000102 的故障分析
· DeepSeek V3 两周使用总结
· 回顾我的软件开发经历(1)
· C#使用yield关键字提升迭代性能与效率
· 低成本高可用方案!Linux系统下SQL Server数据库镜像配置全流程详解
· 4. 使用sql查询excel内容