使用scrapy制作一个小说爬虫
来自: 梦魇
本小说爬虫是为<a href="http://www.ydzww.com">易读中文网</a>创作的 scrapy是用python语言编写的一个爬虫框架,使用的是twisted的异步功能,编写出来的爬虫是无阻塞的,能够最大限度的提高IO。HTML分析模块是使用的lxml,这个是c语言的python绑定,速度特别快,而且使用xpath+re提取内容要比单纯使用re简单明了,有关于scrapy的一些信息,大家就自行百度,百度不出来的就google 我的开发环境是windows,安装scrapy比较麻烦,其实主要是那几个c程序的绑定库安装起来麻烦,自行google解决,这里提供一个网址,里面有很多编译好的包,直接安装就可以了 Unofficial Windows Binaries for Python Extension Packages 下面说一下在ubuntu中的安装方式 apt-get install python-dev apt-get install python-lxml apt-get install libffi-dev pip install scrapy 这样就可以直接在命令行中使用scrapy 下面说一下这个爬虫的思路 有了scrapy这个利器后,小说爬虫还是很容易实现的,爬取小说的话,最主要的是两个页面 小说介绍页,在小说介绍页中,能够获取小说名,作者,分类,对于章节目录又分为2种情况,这2中情况分别介绍 章节目录就在介绍页中 介绍页中含有指向章节目录的链接 小说章节页,章节页中包括章节名和章节内容 就上面所说的第一种情况,无非就是多加了一层Request,但是一般的网站获取到指向章节目录的链接后不含域名和前缀,这时可以使用scrapy提供的两个方法 获取域名和前缀使用 get_base_url(response) 拼接URL使用 moves.urllib.parse.urljoin() 这样直接Request()就可以了 获取章节目录最好使用scrapy自带的SgmlLinkExtractor()函数,能省好多事,而且只要xpath是正确的,就不会有其他错误 关于scrapy items 最好创建item后,使用item创建一个ItemLoade,这样在数据进出的时候可以方便控制,例如: default_output_processor = Compose(Join(""), unicode.strip) 在ItemLoade 中添加这个属性,可以在数据从进入pipeline前进行字符串拼接,去除字符串空白,具体的其他用法scrapy文档 使用这个属性也可以自己定义一个函数,比如我定义的一个 class Filter(object): def __init__(self,f="",regex=""): self.filters = f.split("|") _regex = regex if regex else "" self._regex = smart_unicode(_regex) def __call__(self, content): # 去除网页中的url content = map(lambda c:_regex_url.sub(u"",c), content) # 使用正则去除网页中的其他垃圾内容 content = map(lambda c:re.sub(self._regex,u"", c),content) #不会写正则的可以自定义需要过滤的内容 for filter in self.filters: content = map( lambda s: s.replace(smart_unicode(filter),u""), content) return content 可以说使用item Loader的好处是非常多的 关于scrapy pipeline 往数据库写数据的时候,尽量使用twisted的数据库接口,这样可以最大限度的发挥scrapy的异步优势,不过作为一个小说爬虫没有必要跑那么快,所以网络,文件读写,数据库读写都不会成为瓶颈,所以对于数据操作就没有太严格的要求,下面贴一段网友的数据库操作类 from twisted.enterprise import adbapi import datetime import MySQLdb.cursors class SQLStorePipeline(object): def __init__(self): self.dbpool = adbapi.ConnectionPool('MySQLdb', db='mydb', user='myuser', passwd='mypass', cursorclass=MySQLdb.cursors.DictCursor, charset='utf8', use_unicode=True) def process_item(self, item, spider): # run db query in thread pool query = self.dbpool.runInteraction(self._conditional_insert, item) query.addErrback(self.handle_error) return item def _conditional_insert(self, tx, item): #create record if doesn't exist. #all this block run on it's own thread tx.execute("select * from websites where link = %s", (item['link'][0], )) result = tx.fetchone() if result: log.msg("Item already stored in db: %s" % item, level=log.DEBUG) else: tx.execute(\ "insert into websites (link, created) " "values (%s, %s)", (item['link'][0], datetime.datetime.now()) ) log.msg("Item stored in db: %s" % item, level=log.DEBUG) def handle_error(self, e): log.err(e) #该代码片段来自于: http://www.sharejs.com/codes/python/8392 爬虫控制 使用默认配置,scrapy跑的太快了,做爬虫也是要讲道德的 # 同时下载个数 CONCURRENT_REQUESTS = 5 CONCURRENT_REQUESTS_PER_SPIDER = 5 CLOSESPIDER_PAGECOUNT = 100000 CLOSESPIDER_TIMEOUT = 36000 DOWNLOAD_DELAY = 1.5 RETRY_ENABLED = False COOKIES_ENABLED = Fals 刚才写了过滤函数,现在把过滤url的正则贴一下 (http(s)?://.)?(www\.)?[-a-zA-Z0-9@:!$^&\*%.()_\+~#=\uff10-\uff40{}\[\]]{2,256}[\[\]{}!$^\*&@:%._\+~#=()][\[\]{}a-z!$^\*&@:%._\uff10-\uff40\s]{2,6}\b([\[\]-a-zA-Z0-9()@:%_\+.~#?&//=]*) 爬虫优点 能在linux下面完美运行,windows下面能运行,但是有时可能出现log文件乱码 通过和数据库的配置,一本小说对应一个采集站,3分钟循环监控单本小说,保证小说能够在最快的时间采集 运行快速稳定,scrapy的稳定性还是值得肯定的 还有其他的什么拼音化呀,那些对于python来说都是小儿科,随便加个函数就好了这里就不写了 爬虫自从开始部署后,有一个多星期忘了管理了,发现还运行的非常好。基于这个做了个小说站页面非常难看,而且ie下显示更不好,<a href="http://www.ydzww.com">易读中文网</a>
你的回应
回应请先 登录 , 或 注册相关内容推荐
最新讨论 ( 更多 )
- 有没有会python,有偿 (茶茶)
- Python爬虫进阶资料,留言自取 (若愚希音)
- 自学python难吗? (若愚希音)
- Python爬虫进阶资料,留言自取 (若愚希音)
- 如何修改scrapy的DEFAULT_REQUEST_HEADERS? (Maclaurin)