开始学习下scrapy这个爬虫框架,安装过程可以随便google,这里不再赘述
scrapy文档 这里面有个入门教程可以参考
今天示例网站用的是之前的天气查询。将它改成用scrapy来爬取
创建项目
- 首先必须创建一个新的Scrapy项目。 进入打算存储代码的目录中,运行下列命令:
scrapy startproject scrapy_weather
然后就会生成一个空项目,进入其中使用tree
命令可以看到如下目录树:
│ scrapy.cfg
│
└─scrapy_weather
│ items.py
│ middlewares.py
│ pipelines.py
│ settings.py
│ __init__.py
│
├─spiders
│ __init__.py
-
scrapy.cfg
: 项目的配置文件 -
scrapy_weather/
: 该项目的python模块。之后您将在此加入代码。 -
scrapy_weather/items.py
: 项目中的item文件. -
scrapy_weather/pipelines.py
: 项目中的pipelines文件. -
scrapy_weather/settings.py
: 项目的设置文件. -
scrapy_weather/spiders/
: 放置spider代码的目录.
定义item
- 需要从
weather.com.cn
获取到的数据对item进行建模:
import scrapy
class ScrapyWeatherItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
date = scrapy.Field()
title = scrapy.Field()
tem = scrapy.Field()
win = scrapy.Field()
win_lv = scrapy.Field()
pass
编写爬虫
- 在
spiders
目录下新建weather_spider.py
必须继承scrapy.Spider
且有name
,start_urls
,parse()
三个属性
name
会在运行的时候用到,必须唯一
以下是我这个爬虫,也就是用bs4分析网页,不多说了
import scrapy
from scrapy_weather.items import ScrapyWeatherItem
from bs4 import BeautifulSoup
class WeatherSoider(scrapy.Spider):
# name:用于区别Spider。该名字必须是唯一的
name = 'weather'
# 可选。包含了spider允许爬取的域名(domain)列表(list)。 当 OffsiteMiddleware 启用时, 域名不在列表中的URL不会被跟进
allowed_domains = ['weather.com.cn']
# start_urls:包含了Spider在启动时进行爬取的url列表。
# 因此,第一个被获取到的页面将是其中之一。后续的URL则从初始的URL获取到的数据中提取
start_urls = [
"http://www.weather.com.cn/weather/101010100.shtml",
"http://www.weather.com.cn/weather/101020100.shtml",
"http://www.weather.com.cn/weather/101210101.shtml",
]
#parse()是spider的一个方法。被调用时,每个初始URL完成下载后生成的Response对象将会作为唯一的参数传递给该函数。
# 该方法负责解析返回的数据(responsedata),提取数据
def parse(self, response):
item = ScrapyWeatherItem()
html = response.body
soup = BeautifulSoup(html, 'html.parser')
data = soup.find("div", {'id': '7d'})
wea = {}
wea['date'] = data.find_all('h1')
wea['title'] = data.find_all('p',{'class': 'wea'} )
wea['tem'] = data.find_all('p', {'class': 'tem'})
wea['win'] = data.find_all('p', {'class': 'win'})
for w in wea:
item[w] = []
for o in wea.get(w):
if w == 'date':
item[w].append(o.get_text())
elif w == 'title':
item[w].append(o['title'])
elif w == 'win':
win1 = o.find('span')['title']
win2 = o.find('span').find_next()['title']
win_lv = o.i.get_text()
item[w].append('%s %s %s' % (win1, win2, win_lv))
elif w == 'tem':
high = o.find('span').get_text()
lower = o.find('i').get_text()
item[w].append('最高温:%s,最低温:%s' %(high, lower))
return item
处理爬取到的数据
上一步爬虫的item
会返回到Pipeline
中,所以我们在这里处理数据即可,这一步也可以省略,只要在运行命令后加个-o weather.json
,这样也可以将数据保存到这个json文件中
# spider中抓取的数据会返回到这里,我们可以在这里对数据进行保存到文件,数据库等操作
import codecs
class ScrapyWeatherPipeline(object):
def __init__(self):
self.file = codecs.open('G:/python/weather.xml', 'w', encoding='utf-8') # 初始化一个weather.xml的文件
def process_item(self, item, spider):
for i in range(0,7):
s = ''
for sub in item:
s += item[sub][i] + ' '
self.file.write(s+'\n')
if i == 6:
self.file.write('\n')
return item
最后可以在settings.py
中设置一些东西,比如robots.txt
具体我还没仔细看
运行
- 进入项目目录
scrapy crawl weather
这样就会运行了
爬取到的item如下
- 使用命令
scrapy crawl weather -o weather.json
会运行并将数据保存到这个文件中