使用python+BeautifulSoup完成爬虫抓取特定数据的工作,并使用Django搭建一个管理平台,用来协调抓取工作。
因为自己很喜欢Django admin后台,所以这次用这个后台对抓取到的链接进行管理,使我的爬虫可以应对各种后期的需求。比如分时段抓取,定期的对已经抓取的地址重新抓取。数据库是用python自带的sqlite3,所以很方便。
这几天正好在做一个电影推荐系统,需要些电影数据。本文的例子是对豆瓣电影抓取特定的数据。
第一步:建立Django模型
模仿nutch的爬虫思路,这里简化了。每次抓取任务开始先从数据库里找到未保存的(is_save = False)的链接,放到抓取链表里。你也可以根据自己的需求去过滤链接。
python代码:
然后生成相应的表。
还需要一个admin管理后台
第二步,编写爬虫代码
爬虫是单线程,并且每次抓取后都有相应的暂定,豆瓣网会禁止一定强度抓取的爬虫
爬虫根据深度来控制,每次都是先生成链接,然后抓取,并解析出更多的链接,最后将抓取过的链接is_save=true,并把新链接存入数据库中。每次一个深度抓取完后都需要花比较长的时候把链接导入数据库。因为需要判断链接是否已存入数据库。
这个只对满足正则表达式 http://movie.douban.com/subject/(/d+)/ 的地址进行数据解析。并且直接忽略掉不是电影模块的链接。
第一次抓取需要在后台加个链接,比如http://movie.douban.com/chart,这是个排行榜的页面,电影比较受欢迎。
python代码:
#这段代码不能格式化发
# coding=UTF-8
import urllib2
from BeautifulSoup import *
from urlparse import urljoin
from pysqlite2 import dbapi2 as sqlite
from movie.models import *
from django.contrib.auth.models import User
from time import sleep
image_path = 'C:/Users/soul/djcodetest/picture/'
user = User.objects.get(id=1)
def crawl(depth=10):
for i in range(1,depth):
print '开始抓取 for %d....'%i
pages = Crawl_URL.objects.filter(is_save=False)
newurls={}
for crawl_page in pages:
page = crawl_page.url
try:
c=urllib2.urlopen(page)
except:
continue
try:
#解析元数据和url
soup=BeautifulSoup(c.read())
#解析电影页面
if re.search(r'^http://movie.douban.com/subject/(/d+)/$',page):
read_html(soup)
#解析出有效的链接,放入newurls
links=soup('a')
for link in links:
if 'href' in dict(link.attrs):
url=urljoin(page,link['href'])
if url.find("'")!=-1: continue
if len(url) > 60: continue
url=url.split('#')[0] # removie location portion
if re.search(r'^http://movie.douban.com', url):
newurls[url]= crawl_page.weight + 1 #连接有效。存入字典中
try:
print 'add url :'
except:
pass
except Exception.args:
try:
print "Could not parse : %s" % args
except:
pass
#newurls存入数据库 is_save=False weight=i
crawl_page.is_save = True
crawl_page.save()
#休眠2.5秒
sleep(2.5)
save_url(newurls)
#保存url,放到数据库里
def save_url(newurls):
for (url,weight) in newurls.items():
url = Crawl_URL(url=url,weight=weight)
try:
url.save()
except:
try:
print 'url重复:'
except:
pass
return True
第三步,用BeautifulSoup解析页面
抽取出电影标题,图片,剧情介绍,主演,标签,地区。关于BeautifulSoup的使用可以看这里BeautifulSoup技术文档
豆瓣的电影页面并不是很对称,所以有时候抓取的结果可能会有点出入
抓取到的电影