zoukankan      html  css  js  c++  java
  • Scrapy教程——搭建环境、创建项目、爬取内容、保存文件

    1、创建项目

            在开始爬取之前,您必须创建一个新的Scrapy项目。进入您打算存储代码的目录中,运行新建命令。

    例如,我需要在D:0CodingPythonscrapy目录下存放该项目,打开命令窗口,进入该目录,执行以下命令:

    scrapy startproject  tutorial

    PS:tutorial可以替换成任何你喜欢的名称,最好是英文

          该命令将会创建包含下列内容的 tutorial 目录:

    tutorial/
        scrapy.cfg
        tutorial/
            __init__.py
            items.py
            pipelines.py
            settings.py
            spiders/
                __init__.py
                ...

    这些文件分别是:

    scrapy.cfg: 项目的配置文件
    tutorial/: 该项目的python模块。之后您将在此加入代码。
    tutorial/items.py: 项目中的item文件.
    tutorial/pipelines.py: 项目中的pipelines文件.
    tutorial/settings.py: 项目的设置文件.
    tutorial/spiders/: 放置spider代码的目录.

    2、定义Item

            Item 是保存爬取到的数据的容器;其使用方法和python字典类似,并且提供了额外保护机制来避免拼写错误导致的未定义字段错误。我们需要从想要爬取的网站(这里爬取新浪新闻)中获取以下属性:

    新闻大类url、新闻大类title;

    新闻小类url、新闻小类title;

    新闻url、新闻title;

    新闻标题、新闻内容;

           对此,在item中定义相应的字段。编辑tutorial目录中的 items.py 文件:

    [python] view plain copy
     
    1. from scrapy.item import Item, Field  
    2. class TutorialItem(Item):  
    3.     # define the fields for your item here like:  
    4.     # name = scrapy.Field()  
    5.    parent_title = Field()  
    6.    parent_url = Field()  
    7.   
    8.    second_title = Field()  
    9.    second_url = Field()  
    10.    path = Field()  
    11.   
    12.    link_title = Field()  
    13.    link_url = Field()  
    14.    head= Field()  
    15.    content = Field()  
    16.    pass  

    3、编写爬虫(Spider)

           Spider是用户编写用于从单个网站(或者一些网站)爬取数据的类。

           1、sinaSpider.py文件:

           包含了一个用于下载的初始URL,如何跟进网页中的链接以及如何分析页面中的内容,提取生成 item 的方法。为了创建一个Spider,您必须继承 scrapy.Spider 类,且定义以下三个属性:

    name:用于区别Spider。该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。

    start_urls:包含了Spider在启动时进行爬取的url列表。因此,第一个被获取到的页面将是其中之一。后续的URL则从初始的URL获取到的数据中提取。

    parse() 是spider的一个方法。被调用时,每个初始URL完成下载后生成的Response 对象将会作为唯一的参数传递给该函数。该方法负责解析返回的数据(response data),提取数据(生成item)以及生成需要进一步处理的URL的Request 对象。

    当我们爬取了大类,然后这时候没有保存item,而是传递item到小类,爬取完小类之后,我们需要去新闻详情页爬取新闻的内容和标题:

    主要思路是:paser->second_paser->detail_parse

    以下是sinaSpider的全部代码:

    [python] view plain copy
     
    1. # -*-coding: utf-8 -*-  
    2. __author__= 'George'  
    3. import sys, os  
    4. reload(sys)  
    5. sys.setdefaultencoding("utf-8")  
    6. from scrapy.spider import Spider  
    7. from scrapy.http import Request  
    8. from scrapy.selector import Selector  
    9. from tutorial.items import TutorialItem  
    10. base ="d:/dataset/" #存放文件分类的目录  
    11. class SinaSpider(Spider):  
    12.    name= "sina"  
    13.    allowed_domains= ["sina.com.cn"]  
    14.    start_urls= [  
    15.        "http://news.sina.com.cn/guide/"  
    16.    ]#起始urls列表  
    17.   
    18.    def parse(self, response):  
    19.        items= []  
    20.        sel= Selector(response)  
    21.        big_urls=sel.xpath('//div[@id="tab01"]/div/h3/a/@href').extract()#大类的url  
    22.        big_titles=sel.xpath("//div[@id="tab01"]/div/h3/a/text()").extract()  
    23.        second_urls =sel.xpath('//div[@id="tab01"]/div/ul/li/a/@href').extract()#小类的url  
    24.        second_titles=sel.xpath('//div[@id="tab01"]/div/ul/li/a/text()').extract()  
    25.   
    26.        for i in range(1,len(big_titles)-1):#这里不想要第一大类,big_title减去1是因为最后一个大类,没有跳转按钮,也去除  
    27.            file_name = base + big_titles[i]  
    28.            #创建目录  
    29.            if(not os.path.exists(file_name)):  
    30.                os.makedirs(file_name)  
    31.            for j in range(19,len(second_urls)):  
    32.                item = TutorialItem()  
    33.                item['parent_title'] =big_titles[i]  
    34.                item['parent_url'] =big_urls[i]  
    35.                if_belong =second_urls[j].startswith( item['parent_url'])  
    36.                if(if_belong):  
    37.                    second_file_name =file_name + '/'+ second_titles[j]  
    38.                    if(not os.path.exists(second_file_name)):  
    39.                        os.makedirs(second_file_name)  
    40.                    item['second_url'] = second_urls[j]  
    41.                    item['second_title'] =second_titles[j]  
    42.                    item['path'] =second_file_name  
    43.                    items.append(item)  
    44.        for item in items:  
    45.            yield Request(url=item['second_url'],meta={'item_1': item},callback=self.second_parse)  
    46.   
    47.    #对于返回的小类的url,再进行递归请求  
    48.    def second_parse(self, response):  
    49.        sel= Selector(response)  
    50.        item_1= response.meta['item_1']  
    51.        items= []  
    52.        bigUrls= sel.xpath('//a/@href').extract()  
    53.   
    54.        for i in range(0, len(bigUrls)):  
    55.            if_belong =bigUrls[i].endswith('.shtml') and bigUrls[i].startswith(item_1['parent_url'])  
    56.            if(if_belong):  
    57.                item = TutorialItem()  
    58.                item['parent_title'] =item_1['parent_title']  
    59.                item['parent_url'] =item_1['parent_url']  
    60.                item['second_url'] =item_1['second_url']  
    61.                item['second_title'] =item_1['second_title']  
    62.                item['path'] = item_1['path']  
    63.                item['link_url'] = bigUrls[i]  
    64.                items.append(item)  
    65.        for item in items:  
    66.                yield Request(url=item['link_url'], meta={'item_2':item},callback=self.detail_parse)  
    67.   
    68.    def detail_parse(self, response):  
    69.        sel= Selector(response)  
    70.        item= response.meta['item_2']  
    71.        content= ""  
    72.        head=sel.xpath('//h1[@id="artibodyTitle"]/text()').extract()  
    73.        content_list=sel.xpath('//div[@id="artibody"]/p/text()').extract()  
    74.        for content_one in content_list:  
    75.            content += content_one  
    76.        item['head']= head  
    77.        item['content']= content  
    78.        yield item  


             2、pipelines.py

         主要是对于抓取数据的保存(txt),这里把文件名命名为链接中'/'替换成'_'

    [python] view plain copy
     
    1. # -*- coding: utf-8 -*-  
    2.   
    3. # Define your item pipelines here  
    4. #  
    5. # Don't forget to add your pipeline to the ITEM_PIPELINES setting  
    6. # See: http://doc.scrapy.org/en/latest/topics/item-pipeline.html  
    7. from scrapy import signals  
    8. import json  
    9. import codecs  
    10. import sys  
    11. reload(sys)  
    12. sys.setdefaultencoding( "utf-8" )  
    13. class SinaPipeline(object):  
    14.     def process_item(self, item, spider):  
    15.         link_url = item['link_url']  
    16.         file_name = link_url[7:-6].replace('/','_')  
    17.         file_name += ".txt"  
    18.         fp = open(item['path']+'/'+file_name, 'w')  
    19.         fp.write(item['content'])  
    20.         fp.close()  
    21.         return item  

    3、setting.py

        这是设置文件,这里需要设置同时开启的线程数目、日志打印的级别等

    [python] view plain copy
     
    1. # -*- coding: utf-8 -*-  
    2. BOT_NAME = 'tutorial'  
    3.   
    4. SPIDER_MODULES = ['tutorial.spiders']  
    5. NEWSPIDER_MODULE = 'tutorial.spiders'  
    6. ITEM_PIPELINES = {  
    7.     'tutorial.pipelines.SinaPipeline': 300,  
    8. }  
    9. LOG_LEVEL = 'INFO'  
    10. ROBOTSTXT_OBEY = True  


     

    爬取结果

                 这里的文件夹是根据分类,然后创建的;

            这是大类的文件夹,现在我们已经将item都爬下来了,就需要存了,这里只想要存内容,所以直接将item里面的content字段的内容写入txt。

            这里通过将链接进行处理,转换成文件名,最后保存到所属的那个类里;

  • 相关阅读:
    Niagara技术文档汇总
    cPickle对python对象进行序列化,序列化到文件或内存
    html = data.decode('gbk').encode('utf-8')
    用200行Python代码“换脸”
    No module named cv2
    JAVA Calendar具体解释
    千万别用模板给的list.size()巨坑
    div仿checkbox表单样式美化及功能
    动态规划0—1背包问题
    拒绝乱码:做外贸系统,打印俄文快递单时,避免俄文乱码的方法
  • 原文地址:https://www.cnblogs.com/ws0751/p/8183428.html
Copyright © 2011-2022 走看看