代码改变世界

python实现简单爬虫(二)---- 使用urllib等python模块

2014-07-22 02:55  凝月流风  阅读(357)  评论(1编辑  收藏  举报

  之前使用scrapy实现了一个超级简单的爬虫工具,用于抓取豆瓣上面所有的编程书籍信息(由于不需要爬取整个页面的所以链接,所以不需要用到BFS or DFS,只实现顺序抓取下一页)

  这次使用的是python自带的urllib 和urllib2等python模块实现,同样以豆瓣上面的爱情电影信息作为爬取对象,方法与过程其实如出一辙,同样是对每一个页面发出请求后获取响应得到的网页源码,再使用正则表达式去匹配获得所需信息,然后获取下一页的链接继续爬取。

  爬取页面:

  

  网页源码:

  title and link:   

  desc:      

 

      确定要要抓取的页面和信息后,就可以开始写代码啦~用一个类来执行工作,最后将爬取信息存放到movie.json 文件中,代码如下:

# -*- coding:utf-8 -*-
import urllib
import urllib2
import re
import json


class FilmSpider:
    def __init__(self, init_url_):
        self.start_url = init_url_
        self.contain = []
        self.curPage = 1

    def Parse(self):
        nexturl = self.start_url
        while nexturl != None:
            nexturl = self.parsePage(nexturl)
            self.curPage += 1

        f = open('movie2.json', 'a')

        # JsonLinesItemExporter
        """
        for each_item in self.contain:
            tar = json.dumps(each_item, ensure_ascii=False)
            f.write(tar+'\n')
        """
        # JsonItemExporter
        first_item = True
        f.write('[')
        for each_item in self.contain:
            if first_item:
                first_item = False
            else:
                f.write(',\n')
            tar = json.dumps(each_item, ensure_ascii=False)
            f.write(tar)
        f.write(']')
        f.close()

    def parsePage(self, cururl):
        print('sola is scrawling the %d page: '%self.curPage + cururl)
        response = urllib2.urlopen(cururl)
        body = response.read()
        #返回所有在<tr class="item"></tr>中的字符串的list
        myItems = re.findall('<tr class="item">(.*?)</tr>', body, re.S)
        for item in myItems:
            # 返回所有title 和link组成的tuple所组成的list, 其实list中只有一个tuple
            info = re.findall('<a.*?class="nbg".*?href="(.*?)".*?title="(.*?)">', item, re.S)
            # 返回<p>内的描述所构成的list, 同理只有一个元素
            desc = re.findall('<p.*?class="pl">(.*?)</p>', item, re.S)
            #newItem =  Item(info[0][0], info[0][1], desc[0])

            newItem = {}
            newItem['link'] = info[0][0]
            newItem['title'] = info[0][1]
            newItem['desc'] = desc[0]
            self.contain.append(newItem)
            print newItem['title']
            print newItem['link']
            print newItem['desc']
            print ('\n\n------------------------------------------------------------------------------------------------\n\n')

        Next = re.findall('<span.*?class="next">.*?<link.*?rel="next".*?href="(.*?)"/>', body, re.S)
        if Next:
            return Next[0]
        return None



#-------------------------Main--------------------
#program: spider for Love in Douban
#author : Patrick
#-------------------------------------------------

print('-----------------Start crawl----------------------')

initurl = 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=0&type=T'
solaSpider = FilmSpider(initurl)
solaSpider.Parse()

print('-----------------End crawl------------------------')

 

  代码中关于json文件的存储由两种方式,对应于scrapy框架中的两种存储方式(JsonLinesItemExporter 和 JsonItemExporter 都继承于BaseItemExporter):

  1. JsonLinesItemExporter: 也就是将每一个item转换成json格式后写入,对应与Scrapy中的代码如下:

  

  

  2. JsonItemExporter: 将所有转换成json格式的item再统一放进一个list里面,对应scrapy代码如下:

  

 

  好啦,得到的movie.json 就是酱:

  

 

  下面是用多线程版本进行爬取,使用了5个线程,速度比上面单线程快了很多

# -*- coding:utf-8 -*-

import urllib
import urllib2
import re
import json
import thread
import threading



class FilmSpider:
    def __init__(self, init_url_):
        self.start_url = init_url_
        self.contain = []
        self.curPage = 0

    def Parse(self):

        i = 0
        th = []
        while i < 5:
            pid = threading.Thread(target=self.parsePage, args=(self.start_url[i],i))
            pid.start()
            th.append(pid)
            i = i+1
        i = 0
        while i < 5:
            th[i].join()
            i = i+1

        f = open('movie2.json', 'a')

        # JsonLinesItemExporter
        """
        for each_item in self.contain:
            tar = json.dumps(each_item, ensure_ascii=False)
            f.write(tar+'\n')
        """
        # JsonItemExporter
        first_item = True
        f.write('[')
        for each_item in self.contain:
            if first_item:
                first_item = False
            else:
                f.write(',\n')
            tar = json.dumps(each_item, ensure_ascii=False)
            f.write(tar)
        f.write(']')
        f.close()

    def parsePage(self, cururl, ID):
        print('sola is scrawling the %d page: '%ID + cururl)
        response = urllib2.urlopen(cururl)
        body = response.read()
        #返回所有在<tr class="item"></tr>中的字符串的list
        myItems = re.findall('<tr class="item">(.*?)</tr>', body, re.S)
        for item in myItems:
            # 返回所有title 和link组成的tuple所组成的list, 其实list中只有一个tuple
            info = re.findall('<a.*?class="nbg".*?href="(.*?)".*?title="(.*?)">', item, re.S)
            # 返回<p>内的描述所构成的list, 同理只有一个元素
            desc = re.findall('<p.*?class="pl">(.*?)</p>', item, re.S)
            #newItem =  Item(info[0][0], info[0][1], desc[0])

            newItem = {}
            newItem['link'] = info[0][0]
            newItem['title'] = info[0][1]
            newItem['desc'] = desc[0]
            self.contain.append(newItem)
            """
            print (newItem['title'])
            print (newItem['link'])
            print (newItem['desc'])
            print ('\n\n------------------------------------------------------------------------------------------------\n\n')
            """

        Next = 'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start='
        Next += str((ID+5)*20) + '&type=T'
        Next = Next.strip()
        if ID+5 > 274:
            thread.exit()
        self.parsePage(Next, ID+5)



#-------------------------Main--------------------
#program: spider for Love in Douban
#author : Patrick
#-------------------------------------------------

print('-----------------Start crawl----------------------')

initurl = ['http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=0&type=T',
           'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=20&type=T',
           'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=40&type=T',
           'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=60&type=T',
           'http://movie.douban.com/tag/%E7%88%B1%E6%83%85?start=80&type=T'
          ]

solaSpider = FilmSpider(initurl)
solaSpider.Parse()

print('-----------------End crawl------------------------')