2018-12-01-5-scrapy-爬虫主程序代码分析

11月8号,发了一个预告,然后咕了好几个星期,这次先直接发代码。
项目整体代码地址:pan.baidu.com/s/15bR4Ciu3YFfXYZz5z9jtXA 提取码: pmqv。

下载项目,默认当看到当前页面各位,已经配置好scrapy,配置好mysql,启动main.py。

parse_detail——这个函数的作用是采集本项目的最终页面内容,
就是采集虾米音乐网的歌手某一首歌曲的信息。不过由于我本身写的xpath不够细致,所以导致下面采集具体内容的时候,会出现各种采集不到数据的情况。因此,代码可以借鉴,但是还可以修改。

album_html_urls——函数是专辑歌曲列表页面。如果不知道这个函数是什么内容,可以直接在def下面,直接输入print (response.text),查看生成后的内容。注意内容过多的话,会导致IDE卡死哦。

# -*- coding: utf-8 -*-
import scrapy
from scrapy.http import Request
from urllib import parse
from xiamiuser.items import XiamiuserItem
import requests
'''
title 标题
album 专辑
singer_list 演唱者

obj匹配专辑演唱者等信息
words 作词
composer 作曲
compose 编曲


'''

class XiamiSpider(scrapy.Spider):
    name = 'xiami'
    allowed_domains = ['xiami.com']
    start_urls = ['https://i.xiami.com/musician/artists']


    # 该函数采集的是歌手单个专辑列表
    # 当前正在写mysql入库的功能,所以注销了parse → singer_next_url这块明星列表代码,免得一直在采集列表(有50页)
    # 

    def parse(self, response):
        singer_urls = response.xpath('//div[@class="artist"]/div[@class="info"]/p/strong/a/@href').extract()
        for singer_url in singer_urls:
            singer_url = 'https:' + singer_url
            yield Request(singer_url, callback=self.album_page,dont_filter=True)
            #这个yield里面,dont_filter=True这个,谷歌搜索了 scrapy 301相关的代码,他们说 要么在settings里加一个HTTPERROR_ALLOWED_CODES = [301]
            #上面这个注释来源:https://blog.csdn.net/xueba8/article/details/81841408

        singer_next_url = response.xpath(
            '//div[@class="wrapper"]/div[@class="content_wrapper"]/div[@class="content"]/div[@class="loadr"]/a/@href').extract()
        if singer_next_url:
            singer_next_url = singer_next_url[0]
            print(response.url, singer_next_url)
            yield Request(url=parse.urljoin(response.url, singer_next_url), callback=self.parse)
    def album_page(self, response):
        url = response.url + '/album'
        yield Request(url, callback=self.album_page_album)

    def album_page_album(self, response):
        album_urls = response.xpath('//div[@class="album_item100_thread"]/div[@class="info"]/div[@class="detail"]/p[@class="name"]/a/@href')
        for album_url in album_urls.extract():
            album_url = 'https:' + album_url
            yield Request(album_url, callback=self.album_html_urls)

        next_url = response.xpath(
            '//div[@id="artist_albums"]/div[@class="all_page"]/a[@class="p_redirect_l"]/@href').extract()
        if next_url:
            next_page_url = 'https://i.xiami.com' + next_url[0]
            print(response.url, next_page_url)
            yield Request(next_page_url, callback=self.album_page_album)

    def album_html_urls(self, response):
        album_html = response.xpath('//div[@class="chapter mgt10"]/table/tbody/tr/td[@class="song_name"]/a[1]/@href')
        if album_html:
            for album_html_url in album_html.extract():
                yield Request(url=parse.urljoin('https://www.xiami.com', album_html_url), callback=self.parse_detail)

    def parse_detail(self, response):
        item = XiamiuserItem()
            # 考虑到最终单曲页面,比如说那些纯音乐的可能就只有专辑和歌手,所以重新写。
            # 单曲页面单曲标题
        title = response.xpath('//div[@id="title"]/h1/text()')
        item['title'] = '' if not title else title.extract()[0]

        # 单曲页面所属专辑
        album = response.xpath('//table[@id="albums_info"]/tr[1]/td[2]/div/a/text()')
        item['album'] = '' if not album else album.extract()[0].strip()

        obj_tags = response.xpath('//table[@id="albums_info"]/tr/td/text()').extract()
        for _ in obj_tags:
            # 考虑到最终单曲页面,比如说那些纯音乐的可能就只有专辑和歌手,所以重新写。
            # 单曲页面单曲标题
            if str(_[:-1]) == "演唱者":
        # 单曲页面演唱者
                singer_list = response.xpath(
                    '//table[@id="albums_info"]/tr[2]/td[2]/div/a/text()').extract()
                # 可能有多个演唱者
                if len(singer_list) > 1:
                    singer_list = [i.strip() for i in singer_list]
                    item['singer'] = ','.join(singer_list)
                elif len(singer_list) == 1:
                    item['singer'] = singer_list.extract()[0].strip()
                else:
                    item['singer'] = ''

        if "作词" in response.text:
            # 单曲页面作词
            item['words'] = response.xpath('//table[@id="albums_info"]/tr[2]/td[2]/div/text()').extract()[0].strip()

        else:
            item['words'] = ''

        if "作曲" in response.text:
            zq = response.xpath('//table[@id="albums_info"]/tr[3]/td/text()').extract()[0].strip()[:-1]
            if zq == '作曲':
            # 单曲页面作曲
                item['song'] = response.xpath('//table[@id="albums_info"]/tr[3]/td[2]/div/text()').extract()[0].strip()
        else:
            item['song'] = ''
            # 单曲页面编曲

        if "编曲" in response.text:
            item['compose'] = response.xpath(
                '//table[@id="albums_info"]/tr[5]/td[2]/div/text()').extract()[0].strip()
        else:
            item['compose'] = None

        if "lrc_main" in response.text:
            lyric = response.xpath('//div[@class="lrc_main"]/text()')
            item['lyric'] = [_.strip() for _ in lyric.extract()]
        else:
            item['lyric'] = None

        yield item

上面是爬虫主程序的全部代码,下面要一步步分析爬虫代码的编写。

虾米网爬虫结构.jpg

allowed_domains
允许此爬虫抓取的域的字符串的可选列表,指定一个列表可以抓取,其它就不会抓取了。

start_urls
当没有指定特定网址时,爬虫将开始抓取的网址列表。

首先来到spiders目录下,打开xiami.py


实际代码

按照图片的样子,修改代码。
然后切换到项目文件夹最外一层,新建一个main.py文件,内容如下:


main文件内容

然后启动这个main.py文件。出现以下的调试内容。
调试图.jpg

往下拉一点,能发现输出的内容中,有html源代码的内容

<!DOCTYPE html>
……
</html>

推荐阅读更多精彩内容