基于scrapy的爬虫项目

    科技2022-07-14  157

    基于scrapy的爬虫项目——爬取学校新闻页为例

    目录

    scrapy爬虫框架简介新闻页面html分析一级页面爬取二级页面爬取json格式转换为csv格式结果展示

    1.scrapy爬虫框架简介

    网络上各种scrapy的简介有很多,列举一个如下: https://blog.csdn.net/zjiang1994/article/details/52779537 这里只简单介绍一下各个模块的大致作用。 创建好爬虫之后的文件目录如下: 其中spider文件夹用于存放爬虫,items.py文件用于存储爬取数据,pipelines.py文件用于对爬取的数据进行处理,如写入json或者csv文件中。其中,这几个文件都可以自定义使用。比如我就自定义了一个MyPipelines.py文件用于处理数据。

    2.新闻页面html分析

    我们在html页面中寻找有用的数据时一般使用xpath进行寻找。xpath的一个教程如下: https://blog.csdn.net/a417197457/article/details/81143112 或者可以直接复制,方法如下: 打开开发人员调试器(F12),找到你需要的数据,右击选择copy,选择xpath。这样就可以直接复制xpath。 打开新闻页面进行html分析: 我们要爬取的数据是title,meta,text 使用xpath爬取。这里介绍一个调试xpath的方法。 打开cmd,切入到爬虫所在目录,输入:

    scrapy shell "your_url"

    可以直接进入你需要的url进行分析。 输入:

    response.xpath("your_xpath").extract()

    extract()函数用于提取字符串,即可查看是否是你需要的数据。 根据这个方法就可以分别提取出你需要的数据的xpath。

    3.一级页面爬取

    首先,我们打开items.py,更改items.py用于存储我们需要的数据:

    # Define here the models for your scraped items # # See documentation in: # https://docs.scrapy.org/en/latest/topics/items.html import scrapy #更改item用于存放爬取内容 class SuibenewsItem(scrapy.Item): # 新闻标题 title = scrapy.Field() # 新闻日期 meta = scrapy.Field() # 文本 text = scrapy.Field() # 二级页面爬取的数据存放 title_detail = scrapy.Field() date = scrapy.Field() msg_from = scrapy.Field() visit_count = scrapy.Field() pass

    然后我们在spider文件夹下创建MySpider.py,用于爬取数据。 这个爬虫对象必须要继承scrapy.Spider,有如下几个属性:

    class MySpider(scrapy.Spider): #用于区别Spider name = "MySpider" #允许访问的域 allowed_domains = ["news.suibe.edu.cn"] #爬取的地址 start_urls = ["http://news.suibe.edu.cn/12512/list.htm"]

    下面就可以开始写我们的爬虫:

    def parse(self, response): item = SuibenewsItem() for box in response.xpath('//div[@class="news_box"]'): item["title"] = box.xpath('.//div[@class="news_title"]/a/text()').extract()[0] item["meta"] = box.xpath('.//div[@class="news_meta"]/span/text()').extract()[0] #当text不存在时 if box.xpath('.//div[@class="cols_text"]/a/text()').extract(): item["text"] = box.xpath('.//div[@class="cols_text"]/a/text()').extract()[0] else: item["text"] = "no text" yield item # url跟进开始 # 获取下一页的url信息 count_page = 1 #控制爬取页数 url = response.xpath('//li[@class="page_nav"]//a[@class="next"]/@href').extract() print(url) if url and count_page<=2: count_page+=1 # 将信息组合成下一页的url page = 'http://news.suibe.edu.cn/' + url[0] # 返回url yield scrapy.Request(page, callback=self.parse) # url跟进结束

    url跟进是用于翻页处理,即将request传给下一个页面,然后在进行爬取操作。 这里遇到了一个小问题,即有的新闻没有text,所以增加了一个判断代码,如果没有text就自动添加。

    4.二级页面爬取

    在实际爬取中,我们往往不止需要爬取一级页面,还需要爬取二级页面的一些信息。其实爬取方法和爬取一级页面几乎相同。爬取方法如下:

    #定义爬取子页面的爬取方法 def parseDetail(self,response): #xpath获取数据 title_detail = response.xpath('//div[@class="article"]/h1/text()').extract()[0] date = response.xpath('//div[@class="article"]/p//span[@class="article-update"]/text()').extract()[0] msg_from = response.xpath('//div[@class="article"]/p//span[@class="article-update"]/text()').extract()[1] visit_count = response.xpath('//div[@class="article"]/p//span[@class="WP_VisitCount"]/text()').extract()[0] #取出meta的item item = response.meta['item'] #加入新内容 item["title_detail"] = title_detail item["date"] = date item["msg_from"] = msg_from item["visit_count"] = visit_count yield item

    然后我们需要对以及爬取进行一些处理,将一级爬取的后一段代码改为如下:

    url = response.xpath('//div[@class="cols_more"]/a/@href').extract()[0] url = "http://news.suibe.edu.cn/"+url yield scrapy.Request(url = url,callback=self.parseDetail,meta={'item':item})

    具体意思是,爬取一级页面数据时,将二级页面的url爬取,进行组合,然后使用scrapy.Request()函数传递到目标页面,进行二级页面爬取操作,并将item传递过去。 这样,二级页面的爬取就完成了。 完整代码如下:

    #引入文件 import scrapy from suibenews.items import SuibenewsItem class MySpider(scrapy.Spider): #用于区别Spider name = "MySpider" #允许访问的域 allowed_domains = ["news.suibe.edu.cn"] #爬取的地址 start_urls = ["http://news.suibe.edu.cn/12512/list.htm"] #爬取方法 #定义爬取子页面的爬取方法 def parseDetail(self,response): #xpath获取数据 title_detail = response.xpath('//div[@class="article"]/h1/text()').extract()[0] date = response.xpath('//div[@class="article"]/p//span[@class="article-update"]/text()').extract()[0] msg_from = response.xpath('//div[@class="article"]/p//span[@class="article-update"]/text()').extract()[1] visit_count = response.xpath('//div[@class="article"]/p//span[@class="WP_VisitCount"]/text()').extract()[0] #取出meta的item item = response.meta['item'] #加入新内容 item["title_detail"] = title_detail item["date"] = date item["msg_from"] = msg_from item["visit_count"] = visit_count yield item def parse(self, response): item = SuibenewsItem() for box in response.xpath('//div[@class="news_box"]'): item["title"] = box.xpath('.//div[@class="news_title"]/a/text()').extract()[0] item["meta"] = box.xpath('.//div[@class="news_meta"]/span/text()').extract()[0] #当text不存在时 if box.xpath('.//div[@class="cols_text"]/a/text()').extract(): item["text"] = box.xpath('.//div[@class="cols_text"]/a/text()').extract()[0] else: item["text"] = "no text" url = response.xpath('//div[@class="cols_more"]/a/@href').extract()[0] url = "http://news.suibe.edu.cn/"+url yield scrapy.Request(url = url,callback=self.parseDetail,meta={'item':item}) # url跟进开始 # 获取下一页的url信息 count_page = 1 #控制爬取页数 url = response.xpath('//li[@class="page_nav"]//a[@class="next"]/@href').extract() print(url) if url and count_page<=2: count_page+=1 # 将信息组合成下一页的url page = 'http://news.suibe.edu.cn/' + url[0] # 返回url yield scrapy.Request(page, callback=self.parse) # url跟进结束

    然后我们需要对piplines.py进行处理,对数据进行存储。 创建MyPiplines.py,将数据按照json文件方式存储:

    from scrapy.exceptions import DropItem import json class MyPipeline(object): def __init__(self): #打开文件 self.file = open('news.json', 'w', encoding='utf-8') #该方法用于处理数据 def process_item(self, item, spider): #读取item中的数据 line = json.dumps(dict(item), ensure_ascii=False) + "\n" #写入文件 self.file.write(line) #返回item return item #该方法在spider被开启时被调用。 def open_spider(self, spider): pass #该方法在spider被关闭时被调用。 def close_spider(self, spider): pass

    5.json文件转csv文件

    由于爬取数据是json格式文件,可以通过json库将其转为csv格式文件,具体方法如下(网上找的):

    import json import codecs import pandas as pd def trans(path): jsonData = codecs.open(path+'.json', 'r', 'utf-8') csvfile = open(path+'.csv', 'w', newline='',encoding="utf-8") flag = True csv_data = [] for line in jsonData: dic = json.loads(line[0:-1]) if flag: csv_key = list(dic.keys()) flag = False csv_data.append(list(dic.values())) jsonData.close() data_csv=pd.DataFrame(columns=csv_key,data=csv_data) print(data_csv["text"]) data_csv.to_csv(csvfile) if __name__ == '__main__': path='news' # 获取path参数 print (path) trans(path)

    6.结果展示

    输入以下代码运行爬虫:

    scrapy crawl MySpider

    然后就可以看到爬虫在爬取数据。 我控制了爬取数量,所以得到的结果如下 json格式文件: csv文件: 总体来说,因为是简单页面的爬取,使用scrapy十分的方便。

    Processed: 0.012, SQL: 8