网页新闻抓取(创建一个爬虫模板3.1创建crawlcrawl模板(注意在文件的根目录) )
优采云 发布时间: 2022-03-23 04:19网页新闻抓取(创建一个爬虫模板3.1创建crawlcrawl模板(注意在文件的根目录)
)
1. 新项目
在命令行窗口输入scrapy startproject news,如下
然后自动创建相应的文件,如下
关于各个文件的作用,上一篇博客有详细介绍,可以回看
2. 修改itmes.py文件,打开scrapy框架自动创建的items.py文件,如下
在里面写代码,确定我要获取的信息,比如线程、新闻标题、url、时间、来源、来源url、新闻内容等。
import scrapy
class NewsItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
news_thread = scrapy.Field()
news_title = scrapy.Field()
news_url = scrapy.Field()
news_time = scrapy.Field()
news_source = scrapy.Field()
source_url = scrapy.Field()
news_body = scrapy.Field()
3.定义爬虫并创建爬虫模板3.1 创建爬虫爬虫模板
在命令行窗口下创建爬虫模板(注意文件根目录下,命令检查不要输入错误,-t表示使用下面的爬虫模板),会生成一个news163.py文件在spider文件夹中生成
然后看看这个‘爬取’模板和通用模板的区别。还有更多的链接提取器和一些爬虫规则,这将有助于我们爬取一些深入的信息。
3.2 补充知识点:选择器选择器
支持xpath和css,在css选择器之前的爬虫案例中介绍过,这里是补充xpath的操作,xpath的语法如下
/html/head/标题
/html/head/title/text()
//td(两个用于深度提取/)
//div[@class='我的']
3.3. 分析网页内容
在谷歌chrome浏览器中输入Web News的网站,选择View Source Code,确认可以获取到itmes.py文件的内容(其实我们要获取的是查看源代码网页,然后确认可用)
确认title、time、url、source url和content都可以检查和匹配标签,比如body part
4.修改spider下创建的爬虫文件4.1 导入包
打开创建好的爬虫模板,编写代码。除了导入系统自动创建的三个库外,我们还需要导入news.items(这里涉及到包的概念,以及开头提到的--init-.py文件的存在说明这个文件夹是无需安装直接导入的包)
注意:使用的ExampleSpider类必须继承自CrawlSpider,因为一开始我们创建了一个'crawl'爬虫模板,对应上面
import scrapy
from news.items import NewsItem
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
class New163Spider(CrawlSpider):
name = 'new163'
allowed_domains = ['new163.com']
start_urls = ['http://new163.com/']
rules = (
Rule(LinkExtractor(allow=r'/18/04\d+/*'), callback='parse_news', follow=True),
)
def parse_item(self, response):
item = {}
#item['domain_id'] = response.xpath('//input[@id="sid"]/@value').get()
#item['name'] = response.xpath('//div[@id="name"]').get()
#item['description'] = response.xpath('//div[@id="description"]').get()
return item
Rule(LinkExtractor(allow=r'/18/04\d+/*'), callback='parse_news', follow=True),其中第一个允许是写正则表达式(也是我们需要在核心输入的) ,第二个是回调函数,第三个表示是否允许深
4.2 正则表达式简介
系统的介绍会在爬虫项目中讲解。以下是本项目可以用到的一些基础知识点。正则表达式由字符和运算符组成。常用语法如下
记住一个:“。*?” 是懒惰匹配,匹配只成功一次,可以解决大部分问题,有些需要自己写
比较新闻的标签,如下
第一条新闻的网址是:“”
第二条新闻的网址是:“”
…
规则可见,所以正则表达式可以写成如下
rules = (
Rule(LinkExtractor(allow=r'https://news.163.com/20/0204/\d+/.*?html'), callback='parse_item', follow=True),
)
然后在命令行窗口运行命令:scrapy crawl news163
输出结果为:请求返回200,表示请求成功
4.3 回调函数
parse_item 是我们要设置的回调函数。首先我们处理两个比较简单的获取内容,get thread(去掉url最后五个字符的内容)和title(一般是网页源码的一个title标签中的内容),代码设置如下跟随
def parse_item(self, response):
item = NewsItem()
item['news_thread'] = response.url.strip().split("/")[-1][:-5]
self.get_title(response,item)
return item
def get_title(self,response,item):
title = response.css('title::text').extract()
if title:
print("title:{}".format(title[0]))
item['news_title'] = title[0]
保存后运行命令行窗口,输出如下
然后获取时间,在页面上选择check,在源码中找到新闻时间对应的标签信息,然后使用css选择器查找标签信息,如下
获取新闻时间的代码如下。时间后的内容是一种字符串处理的方法。目的是获取正常格式的时间数据。
self.get_time(response,item) #这个代码要放在回调函数里面
def get_time(self,response,item):
time = response.css('div.post_time_source::text').extract()
if time:
print('time:{}'.format(time[0].strip().replace("来源","").replace('\u3000:',"")))
item['news_time'] = time[0].strip().replace("来源","").replace('\u3000:',"")
输出是:
接下来获取新闻源,查看网页源码,发现新闻源在storage id标签下,可以直接搜索锁定标签(id只有一)
获取消息源的代码如下
self.get_source(response,item) #这个代码要放在回调函数里面
def get_source(self,response,item):
source = response.css("ne_article_source::text").extract()
if source:
print("source:{}".format(source[0]))
item['news_source'] = source[0]
获取原创新闻的URL的方式也差不多,这里直接上代码(注意这里不是id标签的文字内容,而是属性)
self.get_source_url(response,item)
def get_source_url(self,response,item):
source_url = response.css("ne_article_source::attr(href)").extract()
if source_url:
print("source_url:{}".format(source_url[0]))
item['source_url'] = source_url[0]
获取新闻内容,也可以直接给出参考代码如下
self.get_text(response,item)
def get_text(self,response,item):
text = response.css(".post_text p::text").extract()
if text:
print("text:{}".format(text))
item['news_body'] = text
获取新闻网址(原文),也直接给出参考代码如下
self.get_url(response,item)
def get_url(self,response,item):
url = response.url
if url:
item['news_url'] = url
至此,news163.py的所有代码编写如下:
import scrapy
from news.items import NewsItem
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
#https://news.163.com/20/0205/06/F4JOHHEJ0001899O.html
#https://news.163.com/20/0205/08/F4JVQU6P000189FH.html
class News163Spider(CrawlSpider):
name = 'news163'
allowed_domains = ['news.163.com']
start_urls = ['http://news.163.com/']
rules = (
Rule(LinkExtractor(allow=r'https://news.163.com/20/0205/\d+/.*?html'), callback='parse_item', follow=True),
)
def parse_item(self, response):
item = NewsItem()
item['news_thread'] = response.url.strip().split("/")[-1][:-5]
self.get_title(response,item)
self.get_time(response,item)
self.get_source(response,item)
self.get_source_url(response,item)
self.get_text(response,item)
self.get_url(response,item)
return item
def get_url(self,response,item):
url = response.url
if url:
item['news_url'] = url
def get_text(self,response,item):
text = response.css(".post_text p::text").extract()
if text:
print("text:{}".format(text))
item['news_body'] = text
def get_source_url(self,response,item):
source_url = response.css("ne_article_source::attr(href)").extract()
if source_url:
#print("source_url:{}".format(source_url[0]))
item['source_url'] = source_url[0]
def get_source(self,response,item):
source = response.css("ne_article_source::text").extract()
if source:
print("source:{}".format(source[0]))
item['news_source'] = source[0]
def get_time(self,response,item):
time = response.css('div.post_time_source::text').extract()
if time:
print('time:{}'.format(time[0].strip().replace("来源","").replace('\u3000:',"")))
item['news_time'] = time[0].strip().replace("来源","").replace('\u3000:',"")
def get_title(self,response,item):
title = response.css('title::text').extract()
if title:
print("title:{}".format(title[0]))
item['news_title'] = title[0]
保存后运行命令行的输出如下(注意,注意,注意,调试过程中不要频繁运行此命令,否则会无法访问服务器),只会截取部分输出结果
5.修改管道文件下的内容5.1 导入csv文件存储包
要在本地存储数据,需要一种格式作为存储的条件。逗号分隔(csv)文件可以满足这个要求,也是现在存储数据的主要工具。
from scrapy.exporters import CsvItemExporter
5.2 定义流程函数
首先从初始化函数开始,其中收录采集数据文件的创建和项目启动器
def __init__(self):
self.file = open('news_data.csv', 'wb')
self.exporter = CsvItemExporter(self.file, encoding = 'utf-8')
self.exporter.start_exporting()
二、定义爬虫终结者,完成项目,关闭进程和文件,防止内存溢出
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
最后在处理函数中,打开import,最后返回Item
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
至此,管道中的代码编写已经完成。这时候需要在setting.py文件中打开管道通道,取消注释以下内容,如下
最后整个pipeline.py的文件代码如下,注意检查缩进问题(Sublime编辑器有一个选项可以将所有缩进转换成tab格式,保证缩进一致,注意缩进的问题网页编码,否则会出现乱码的情况,编码要根据爬取网页的编码格式设置)
from scrapy.exporters import CsvItemExporter
class NewsPipeline(object):
def __init__(self):
self.file = open('news_data.csv', 'wb')
self.exporter = CsvItemExporter(self.file, encoding = 'gbk')
self.exporter.start_exporting()
def close_spider(self,spider):
self.exporter.finish_exporting()
self.file.close()
def process_item(self, item, spider):
self.exporter.export_item(item)
return item
6. 运行结果
最后在命令行窗口中运行命令,当窗口界面出现爬取内容输出时,news文件夹中也自动生成了news_data.csv文件,如下
news_data.csv文件中的数据样式如下,至此整个使用Scrapy抓取网页新闻的项目全部结束