一,准备工作
需要安装好python3,scrapy,mongodb
二,创建项目
(一);创建scrapy 项目
打开cmd 输入:scrapy startproject tutorial
cd 到 tutorial 目录
输入:scrapy genspider bole python.jobbole.com/ 可以创建bole.py 的spider项目
在pycharm中打开tutorial 项目
下面一共有以下文件:
├── tutorial
│ ├── items.py
│ ├── middlewares.py
│ ├── pipelines.py
│ ├── __pycache__
│ ├── settings.py
│ ├── spiders
│ │ ├── __init__.py
│ │ ├── bole.py
│ │ └── __pycache__
└── scrapy.cfg
spiders 文件夹:下面存放的是spider项目 ,bole.py就在此文件夹下面,主要的爬虫逻辑是在此编写的
items.py: Item结构 都是在这里定义的
pipelines.py: 主要负责清洗数据和保存数据
settings.py:定义项目的全局配置
middlewares.py:中间件,此项目中没有用这个
scrapy.cfg scrapy项目的配置文件
三,获取数据
打开bole.py
# -*- coding: utf-8 -*-
import scrapy
class BolesSpider(scrapy.Spider):
name = 'bole'
allowed_domains = ['python.jobbole.com']
start_urls = ['http://python.jobbole.com/']
def parse(self, response):
pass
这个是scrapy为我们自动创建好的,首先把start_urls设为python所有文章的第一页的链接:http://python.jobbole.com/all-posts/
解析网页主要是在parse里面编写
首先打开伯乐在线python的全部文章的第一页:http://python.jobbole.com/all-posts/,按f12打开检查,如图,所有的文章页面都是有标题,发表时间,标签和简介组成:
一页有20篇文章,一共是84页:
首先需要在items.py中把需要获取的数据在item中定义:
class BoleItem(scrapy.Item):
title = scrapy.Field()
url = scrapy.Field()
time = scrapy.Field()
tags = scrapy.Field()
jianjie = scrapy.Field()
我们需要获取到标题,文章详情页面链接,发表时间这些内容,可以通过xpath解析获取,scrapy只能可以直接使用xpath解析,为了更加直观的查看获取的数据,方便调试,可以使用 scrapy shell 调试:
在终端cmd中 输入:scrapy shell http://python.jobbole.com/all-posts/
,即可打开进入shell
首先获取标题:通过观看可以发现文章标题是在此结构之下:
1,获取标题:
可以在shell中用xpath解析调试:response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p/a[1]/text()').extract()
可以获取所有标题如图:
2,获取文章详情页面链接:
同理可以获取到url连接,稍加修改就行:response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p/a[1]/@href').extract()
3,获取发表时间:
response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p[1]/text()').extract()
但是获取到的数据有很多空格和其他字符,如图:
除去这些字符可以直接用正则匹配出需要的时间信息,其他的都不要,正则表达式可以这样编写:re.findall('[0-9]{4}/[0-9]{2}/[0-9]{2}
就可以匹配所有的时间
4,获取标签:response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p[1]/a[2]/text()').extract()
5,获取简介:response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/span/p/text()').extract()
这样就获取到了第一页的所有的标题,链接,发表时间,标签,简介了,接下来是获取所有页面的,需要获取到所有页面的链接,并交给解析函数执行,这样循环往复就可以获取所有的信息了
通过点击第二页可以发现,可以通过page/ 后面的数字控制页面,可以循环获取一共84页的页面
代码:
for i in range(1, 85):
url = 'http://python.jobbole.com/all-posts/page/{}/'.format(i)
但是第一页已经通过start_url 获取到了,所以第一页就不用再获取了,把1改为2就行的
使用正则和item 需要导入
import re
from tutorial.items import BoleItem
bole.py完整代码:
# -*- coding: utf-8 -*-
import scrapy
import re
from tutorial.items import BoleItem
class BoleSpider(scrapy.Spider):
name = 'bole'
allowed_domains = ['python.jobbole.com']
start_urls = ['http://python.jobbole.com/all-posts/']
def parse(self, response):
item=BoleItem()
item['title']= response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p/a[1]/text()').extract()
item['url']=response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p/a[1]/@href').extract()
times = response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p[1]/text()').extract()
item['time'] =re.findall('[0-9]{4}/[0-9]{2}/[0-9]{2}',str(times))
item['tags'] =response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/p[1]/a[2]/text()').extract()
item['jianjie']=response.xpath('//div[@class="post floated-thumb"]/div[@class="post-meta"]/span/p/text()').extract()
yield item
for i in range(2, 85):
url = 'http://python.jobbole.com/all-posts/page/{}/'.format(i)
print(url)
yield scrapy.Request(url=url, callback=self.parse)
四,保存数据
获取获取到了,接下来就是要保存数据,
我是保存为TXT文档和mongodb中,保存数据需要在pipelines.py中设置
1,首先是保存的TXT中
首先新建一个 BolePipeline类, 在这个类中实现保存到TXT:
代码如下:
class BolePipeline(object):
# 打开一个TXT文件,没有的话就创建一个
def open_spider(self, spider):
self.file = open('bole.txt', 'a',encoding='utf-8')
# 数据写入TXT文件中
def process_item(self, item, spider):
try:
datas =zip(item['title'], item['url'], item['time'], item['tags'], item['jianjie'])
for data in datas:
self.file.write('标题:{0},连接:{1},发表时间:{2},标签:{3},简介:{4},\n'.format(data[0], data[1], data[2], data[3], data[4]))
except:
print("保存失败")
return item
# 写入完成后,关闭TXT文件
def close_spider(self, spider):
self.file.close()
2,保存到mongodb中
首先需要导入pymongo库,然后新建 MongoPipeline类,在这个类中实现保存到mongodb。
代码如下:
import pymongo
class MongoPipeline(object):
def __init__(self, mongo_uri, mongo_db):
self.mongo_uri = mongo_uri
self.mongo_db = mongo_db
@classmethod
def from_crawler(cls, crawler):
return cls(
mongo_uri=crawler.settings.get('MONGO_URI'),
mongo_db=crawler.settings.get('MONGO_DB')
)
def open_spider(self, spider):
self.client = pymongo.MongoClient(self.mongo_uri)
self.db = self.client[self.mongo_db]
def process_item(self, item, spider):
name = item.__class__.__name__
try:
datas =zip(item['title'], item['url'], item['time'], item['tags'], item['jianjie'])
for data in datas:
info={
'标题':data[0],
'url': data[1],
'发表时间': data[2],
'标签': data[3],
'简介': data[4],
}
self.db[name].insert(info)
except:
print("保存失败")
return item
def close_spider(self, spider):
self.client.close()
最后需要在settings.py中打开Pipeline管道
代码如下:
ITEM_PIPELINES = {
'tutorial.pipelines.BolePipeline': 1,
'tutorial.pipelines.MongoPipeline': 2,
}
此外还有配置mongodb链接信息
MONGO_URI='localhost'
MONGO_DB='tutorial'
这样全部的项目就完成了
运行项目: cd 到 tutorial 目录下面 打开cmd 输入 : scrapy crawl bole 就可以运行项目了
五,实现效果:
保存到TXT文档中的效果:
保存到mongodb中的效果: