近期的计划-出一系列爬虫的文章2

2017-04-12  本文已影响84人  nonoBoy

月底回青海之前,在造数微信群里帮一位朋友爬了豆瓣电影的数据,分享一下心得:
1 、豆瓣电影汇总的链接url = 'https://movie.douban.com/tag/'
2 、通过tag页链接,抓取到所有分类首页链接,代码如下:

import requests
from lxml import etree

url = 'https://movie.douban.com/tag/'
headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0"
}

#获取每个tag对应的url
def getTagURLs(url):
    response = requests.get(url, headers=headers)
    selector = etree.HTML(response.text)

    all_tag = selector.xpath("//div[@class='article']//td//a")
    all_href = selector.xpath("////div[@class='article']//td//a/@href")

    for i in range(len(all_tag)):
        tag = all_tag[i].xpath('string(.)')
        href = 'https://movie.douban.com' + all_href[i]
        print(tag + ': ' + href)

运行上面代码打印如下结果:

类别名: 对应首页链接
爱情: https://movie.douban.com/tag/爱情
喜剧: https://movie.douban.com/tag/喜剧
剧情: https://movie.douban.com/tag/剧情
动画: https://movie.douban.com/tag/动画
科幻: https://movie.douban.com/tag/科幻
动作: https://movie.douban.com/tag/动作
经典: https://movie.douban.com/tag/经典
.....

3、基于以上结果并分析网页很容易构造出所有电影列表的链接:
例如,爱情类电影所有链接符合规律:
https://movie.douban.com/tag/爱情?start=0 (第一页)
https://movie.douban.com/tag/爱情?start=20 (第二页)
https://movie.douban.com/tag/爱情?start=40 (第二页)
...
构造出所有类别的所有页面链接后,写入Mongodb,后面用作多进程抓取的URL队列;下面基于以上代码获取每个类别总的页数并且构造url写入数据库:

import requests
from lxml import etree
from mongodb_queue import MongoQueue

spider_queue = MongoQueue('douban', 'movie')
url = 'https://movie.douban.com/tag/'

headers = {
    'User-Agent': "Mozilla/5.0 (Windows NT 5.1; rv:11.0) Gecko/20100101 Firefox/11.0"
}

#获取每个tag对应的url
def getTagURLs(url):
    response = requests.get(url, headers=headers)
    selector = etree.HTML(response.text)

    all_tag = selector.xpath("//div[@class='article']//td//a")
    all_href = selector.xpath("////div[@class='article']//td//a/@href")

    for i in range(len(all_tag)):
        tag = all_tag[i].xpath('string(.)')
        href = 'https://movie.douban.com' + all_href[i]
        print(tag + ': ' + href)
        
        #通过href获得total-page
        response4 = request.get(href, 3)

        #sleep
        time.sleep(2.0 + random.random())
        selector4 = etree.HTML(response4.text)

        total_page = selector4.xpath("//span[@class='thispage']/@data-total-page")
        total_page = total_page[0]
        print('总的页面数: ' + total_page)

        #构造所以列表页面
        for i in range(int(total_page) + 2):
            page = 20 * i
            listURL = href + '?'+ 'start=' + str(page) +'&type=T'
            print(listURL)
            spider_queue.push(listURL)

写入数据库后,URL队列如下:

{ "_id" : "https://movie.douban.com/tag/爱情?start=0", "status" : 1 }
{ "_id" : "https://movie.douban.com/tag/爱情?start=20", "status" : 1 }
{ "_id" : "https://movie.douban.com/tag/爱情?start=40", "status" : 1}
......

4、基于数据库URL队列,下面开启多进程进行数据抓取(使用代理IP,手动VPN切换IP-几次就能抓完):

from Download import request
from mongodb_queue import MongoQueue
from lxml import etree
import multiprocessing
import time
import random

spider_queue = MongoQueue('douban', 'movie')

def doubanMovieSpider():
    while True:
        try:
            url = spider_queue.pop()
        except:
            print('队列咩有数据')
            break
        else:
            result = getMovies(url)
            #是否抓取成功判断
            if len(result) != 0:
                spider_queue.complete(url)
            else:
                spider_queue.reset(url)

def getMovies(url):
    response2 = request.get(url, 3)
    selector2 = etree.HTML(response2.text)

    all_names = selector2.xpath("//div[@class='pl2']//a")
    all_description = selector2.xpath("////div[@class='pl2']//p")
    all_urls = selector2.xpath("//div[@class='pl2']//a/@href")

    for i in range(len(all_names)):
        name = all_names[i].xpath('string(.)')

        # 去空格
        name = ''.join(name.strip())
        # 去掉内部空格
        name = name.replace('\n', '')
        name = name.replace(' ', '')

        description = all_description[i].xpath('string(.)')
        href = all_urls[i]
        print('电影名称:' + name + ',电影主页URL:' + href, end='\n')
        print(description)

        file4 = open('mydata.txt', 'a')
        file4.write('电影名称:' + name + ',电影主页URL:' + href + '\n' + description + '\n')
        file4.close()

    time.sleep(2.0 + random.random())
    return all_names

#多进程
def process_crawler():
    process= []
    #开启100个进程 期间被封掉了几个IP,用VPN切换IP又可以重新抓取
    #这里使用的方法属于暴力快速抓取
    for i in range(100):
        p = multiprocessing.Process(target=doubanMovieSpider)
        p.start()
        process.append(p)
    for p in process:
        p.join()

if __name__ == "__main__":
    process_crawler()

代码中的Download和mongdb_queue模块参考文章1
最后分享抓到的电影数据,txt格式大概30M;
https://pan.baidu.com/s/1mika4Pi
提取密码:97h7

具体数据格式参考:

电影名称:美女与野兽,电影主页URL:https://movie.douban.com/subject/25900945/
2017-03-17(中国大陆/美国) / 艾玛·沃森 / 丹·史蒂文斯 / 卢克·伊万斯 / 凯文·克莱恩 / 乔什·加德 / 伊万·麦克格雷格 / 伊恩·麦克莱恩 / 艾玛·汤普森 / 斯坦利·图齐 / 古古·姆巴塔-劳 / 奥德拉·麦克唐纳 / 内森·麦克 / 哈蒂·莫拉汉...

电影名称:爱乐之城/星声梦里人(港)/乐来越爱你(台),电影主页URL:https://movie.douban.com/subject/25934014/
2016-08-31(威尼斯电影节) / 2016-12-25(美国) / 2017-02-14(中国大陆) / 瑞恩·高斯林 / 艾玛·斯通 / 约翰·传奇 / 罗丝玛丽·德薇特 / 芬·维特洛克 / 杰西卡·罗德 / 水野索诺娅 / 考莉·赫尔南德斯 / J·K·西蒙斯 / 汤姆·艾弗瑞特·斯科特 / 米根·费伊...
......
上一篇下一篇

猜你喜欢

热点阅读