Python写的deviantArt小爬虫
功能简介
个人兴趣,打算爬个数据库拿来做推荐系统,几经周折终于写出了能稳定运行的D站爬虫。
这个爬虫抓取的内容包括作品名、作者名、上传日期、分类、评分和每个评分者,比较适合于简单的协同推荐算法。
为了效率,采用多线程方式,各线程间利用任务队列同步,结果使用sqlite3模块保存在两个数据库文件中。我的电脑不能24小时运行着它,所以加入了中断恢复的功能。
程序用到的模块如下:
[python]
import urllib2
import sqlite3
import re
import string
from bs4 import BeautifulSoup
import time
import Queue
import threading
import urllib2
import sqlite3
import re
import string
from bs4 import BeautifulSoup
import time
import Queue
import threading
程序流程
各线程功能
1.扩充个人主页线程Extender
这个线程包含了两个功能:抓取首页作者列表,放入个人主页队列中;以及获得现有队列中每一位作者的好友列表,放回到个人主页队列中。
启动后,它会等待中断恢复线程的报告,若没有待完成任务,就开始抓取首页并进行扩充,直到处理的个人主页达到指定量为止。若有待完成任务,则根据控制信号,直接退出(不扩充)或对中断恢复线程提供的队列进行扩充。
[python]
#--------------------------------------------------------------------#
#扩充个人主页列表的线程,输入为已备份主页队列qSaved,输出为已扩充主页队列qExtended和待处理主页队列qProfile
class ExtendProfileThread(threading.Thread):
#初始化
def __init__(self, thread_name, qsaved, qextended, qprofile, repeat=1000):
threading.Thread.__init__(self, name = thread_name)
self.input = qsaved
self.output = qextended
self.recycle = qprofile
self.indexUrl = ''
self.remaincount = repeat
self.isRunning = 0
#读取首页(仅在有首页地址传入时执行)
def readIndex(self):
url_legal_pattern = re.compile('http://.*') #用于检查url合法性的正则表达式模式
strip_tag_pattern = re.compile('</?\w+[^>]*>') #用于去除html标签的正则表达式模式
#检查URL合法性
match = url_legal_pattern.search(indexUrl)
if not match:
print 'Illegal Index URL:', indexUrl
return -1
#读取页面
try:
site = urllib2.urlopen(indexUrl, timeout=10)
content = site.read()
except:
print 'Time out for index:', indexUrl
return -1
#分析HTML结构
soup = BeautifulSoup(content, 'html5lib')
pagetitle = re.sub(strip_tag_pattern, '', soup.html.head.title.__str__())
print '>>Index Page: '+pagetitle+'<<'
#提取title和url信息
articles = soup.findAll('a', attrs = {'href':True, 'title':True, 'class':'thumb'})
for item in articles:
url = item['href']
self.recycle.put(url[:url.find('art/')])
self.remaincount = self.remaincount - 1
site.close()
return 0
#扩充qProfile
def extendProfile(self):
#满足给定扩展次数则线程结束
if self.remaincount <= 0:
print 'Extend repeat finish'
isRunning = 0
return -1
try:
url = self.input.get(block = False)
except Queue.Empty:
return 1 #用于记录qSaved为空重试的次数
self.output.put(url) #将取出的url直接放入qExtended
time.sleep(0.5) #未必需要,防止访问太频繁被服务器打回
retry = 6 #超时重试5次+初始1次
while retry:
try:
page = urllib2.urlopen(url, timeout=10)
content = page.read()
page.close()
except:
if retry > 1:
print 'Time out for watchers:', url
print 'Retry', 7-retry
retry = retry - 1
if not retry:
print 'Cannot connect to url:', url
补充:Web开发 , Python ,