文件介绍
- scrapy.cfg :项目的配置文件
- mySpider/: 项目的python模块,将会从这里引用代码
- mySpider/items.py :项目的目标文件
- mySpider/pipelines.py :项目的管道文件
- mySpider/settings.py:项目的设置文件
启动爬虫
- 首先切换路径 到一个包里
cd _scrapy
- 创建一个工程
scrapy startproject myspider (这是工程名)
- 创建爬虫**
**首先啊要切换到这个工程里cd myspider
- 再在这里面创建爬虫
scrapy genspider itcast itcast.cn
- 启动命令:
scrapy crawl itcast (itcast是爬虫的名字 自己起的)
安装scrapy
-
scrapy安装需要一个异步模块Twisted,这个模块得自己手动安装
-
pycharm 安装:
-
pip install Twisted存放的路径
-
-
**然后 需要升级 运行指令: **
-
pip install pypiwin32
-
itcast.py
# -*- coding: utf-8 -*-
import scrapy
class ItcastSpider(scrapy.Spider):
name = 'itcast'
#这是爬虫的识别名称,必须是唯一的,在不同的爬虫中必须定义不同的名字
allowed_domains = ['http://www.itcast.cn']
#这是搜索的域名范围,也就是爬虫的约束区域,规定爬虫只爬取这个域名下的网页,不存在的URL会被忽略
start_urls = ['http://www.itcast.cn']
#爬取的URL列表,爬虫从这里面开始抓取数据,所以,第一次下载的数据将会从这些urls开始。其他子URL将会从这些起始URL中继承性生成
def parse(self, response):
#解析的方法,每个初始URL完成下载后将被调用,调用的时候传入从每一个URL传回的Response对象来作为唯一参数,主要作用如下:
1、负责解析返回的网页数据,提取结构化数据
2、生成需要下一页的URL请求
print(response)
管道文件就是处理item字段的
def __init__(self): 管道初始执行
def close_spider(self,spider): 爬虫结束执行
# -*- coding: utf-8 -*-
import scrapy
from ..items import ItcomItem
class ItcomSpider(scrapy.Spider):
name = 'ITcom'
allowed_domains = ['citreport.com/news/it/']
start_urls = ['http://www.citreport.com/news/it/']
def parse(self, response):
#标题
title = response.xpath('//*[@id="ct"]/div[1]/div[2]/div[2]/div/div/div/h2/a/text()').extract()
# print(title)
#文章链接
url = response.xpath('//*[@id="ct"]/div[1]/div[2]/div[2]/div/div/div/h2/a/@href').extract()
# print(url)
#图片链接
images = response.xpath('//*[@id="ct"]/div[1]/div[2]/div[2]/div/div/div[1]/a/img/@src').extract()
for index,values in enumerate(title):
item = ItcomItem()
item['title'] = title[index] #标题
item['url'] = url[index] #文章详情页地址
item['image_urls'] = [images[index]] #图片链接
# meta是向下个方法里传递参数 以字典的形式 key:value 可以传递多个参数 dont_filter是url去重
yield scrapy.Request(url=url[index],callback=self.content_parse,method='GET',meta={'item':item},dont_filter=True)
#获取详情页
def content_parse(self,response):
item = response.meta['item']
item1 = response.xpath('//p/text()').extract()
item['content2'] = ''.join(item1)
print(item['content2'])
yield item
pipelines
import scrapy,os
from scrapy.pipelines.images import ImagesPipeline
from pymongo import MongoClient
import json
class FourPipeline(object):
def open_spider(self,spider):
self.client=MongoClient(host='localhost',port=27017)
self.collection=self.client['qimo']['four']
def process_item(self, item, spider):
self.collection.insert_one(dict(item))
return item
def close_spider(self,spider):
self.client.close()
class CrawlImg(ImagesPipeline):
def get_media_requests(self, item, info):
yield scrapy.Request(url=item['img'])
def item_completed(self, results, item, info):
img_path=''.join([x['path'] for ok,x in results if ok])
os.rename('./img/'+img_path,'./img/'+item['title']+'.jpg')
return item
class Write(object):
def open_spider(self,spider):
self.file=open(file='1.json',mode='a',encoding='utf8')
def process_item(self, item, spider):
json.dump(dict(item),self.file,ensure_ascii=False,indent=2)
return item
def close_spider(self,spider):
self.file.close()
settings
ITEM_PIPELINES = {
'four.pipelines.CrawlImg':1,
'four.pipelines.FourPipeline': 300,
'four.pipelines.Write':200
}
IMAGES_STORE='./img/'
xpaths语法
names=response.xpath("//tr[contains(@class,"odd") or contains(@class,"even")]")
scrapy保存信息的最简单的方法主要有四种,-o输出指定格式的文件
- #json格式,默认为unicode编码**
**scrapy crawl itcast -o 文件名.json - #json lines格式,默认为unicode编码**
**scrapy crawl itcast -o 文件名.jsonl - #csv逗号表达式,可用Excel打开**
**scrapy crawl itcast -o 文件名.csv - #xml格式**
**scrapy crawl itcast -o 文件名.xml
翻页、调用其他函数
# meta是向下个方法里传递参数 以字典的形式 key:value 可以传递多个参数 dont_filter是url去重
yield scrapy.Request(url=item['content_urls'],callback=self.crawlContent,meta={'item':item},dont_filter=True)
yield scrapy.Request(url=self.url+str(self.num),callback=self.parse)
懒点下载图片
item['image_urls']=x.xpath(".//div[@class='img']/a/img/@src").extract()[0]
你的item字段名必须是image_urls
xpath返回的永远是个列表 所以你要取[0]
.extract()是将xpath对象转换为unicode对象
爬取多页
import scrapy
from ..items import ThreeItem
class ItcastSpider(scrapy.Spider):
name = 'itcast'
url='http://www.bloggerlee.com/?paged='
num=1
allowed_domains = ['bloggerlee.com']
start_urls = [url+str(num)]
def parse(self, response):
all=response.xpath("//div[@id='content']//div[@class='box-wrap']")
list=[]
for x in all:
item=ThreeItem()
item['title']=x.xpath(".//h2/a/text()").extract()[0]
item['image_urls']=x.xpath("./div/a/img/@src").extract()[0]
item['classify']=x.xpath(".//div[@class='post-content']/ul/li[1]/a/text()").extract()[0]
contentUrl=x.xpath(".//div[@class='read_more']/a/@href").extract()
if contentUrl!=[]:
item['content_urls']=contentUrl[0]
# meta是向下个方法里传递参数 以字典的形式 key:value 可以传递多个参数 dont_filter是url去重
yield scrapy.Request(url=item['content_urls'],callback=self.crawlContent,meta={'item':item},dont_filter=True)
else:
item['content_urls']=' '
list.append(item)
if self.num!=2: #之抓取两页
self.num += 1
yield scrapy.Request(url=self.url+str(self.num),callback=self.parse)
print(list)
def crawlContent(self,response):
item=response.meta['item']
item['content']=''.join(response.xpath("//div[@class='content']/p[position()>1][position()<last()]/text()").extract())
yield item