Scrapy框架
什么是scrapy
Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架,我们只需要实现少量的代码,就能够快速的抓取。
文件目录
scrapy.cfg #项目的配置文件
items.py #提取要爬取的字段,字典保存爬取到的数据的容器
middlewares #自定义中间件的地方
pipelines.py #管道,保存数据
settings.py #项目的设置文件 设置文件,UA,启动管道
spiders #存储爬虫代码目录
itcast.py #写爬虫的文件
爬虫步骤:
1.创建一个scrapy项目
scrapy startproject mySpider #mySpider是项目名字
2.生成一个爬虫
scrapy genspider itcast itcast.cn #itcast是爬虫名字,"itcast.cn"限制爬虫地址,防止爬到其他网站
3.提取数据
完善spiders,使用xpath等方法
4.启动爬虫
scrapy crawl 爬虫名字 #crawl(抓取的意思)
spider内容
spider翻页
# -*- coding: utf-8 -*-
import scrapy
#导入items
from tencent.items import TencentItem
#自定义spider类,继承自scrapy.Spider
class ItcastSpider(scrapy.Spider):
name = 'itcast' #爬虫名字<爬虫启动时候使用:scrapy crawl itcast>
#允许爬取的范围,防止爬虫爬到了别的网站
allowed_domains = ['tencent.com']
#开始爬取的地址,下载中间件提取网页数据
start_urls = ['https://hr.tencent.com/position.php']
#数据提取方法,接收下载中间件传过来的response(响应)
def parse(self, response):
#处理start_url地址对应的响应
#提取数据
# reti = response.xpath("//div[@class='tea_con']//h3/text()").extract()
# print(reti)
#分组,[1:-1]切片,不要第一条数据
li_list = response.xpath("//table[@class="tablelist"]/tr")[1:-1]
for li in li_list:
#在item中定义要爬取的字段,以字典形式传入
item = TencentItem()
item["name"] = li.xpath(".//h3/text()").extract_first()
item["title"] = li.xpath(".//h4/text()").extract_first()
#yield可以返回request对象,BaseItem(items.py中的类),dict,None
yield item #yield传到pipeline
#找到下一页url地址
next_url = response.xpath('//a[@id="next"]/@href').extract_first()
#如果url地址的href="地址"不等于javascript:;
if next_url != "javascript:;":
next_url = "https://hr.tencent.com/"+ next_url
#把next_url的地址通过回调函数callback交给parse方法处理
yield scrapy.Request(next_url,callback=self.parse)
爬取详细页和翻页
# -*- coding: utf-8 -*-
import scrapy
from yangguang.items import YangguangItem
class YgSpider(scrapy.Spider):
name = 'yg'
allowed_domains = ['sun0769.com']
start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=0']
def parse(self, response):
tr_list = response.xpath("//div[@class='greyframe']/table[2]/tr/td/table/tr")
for tr in tr_list:
item = YangguangItem()
item["title"] = tr.xpath("./td[2]/a[@class='news14']/@title").extract_first()
item["href"] = tr.xpath("./td[2]/a[@class='news14']/@href").extract_first()
item["publish_date"] = tr.xpath("./td[last()]/text()").extract_first()
#执行进入url地址,再把item传到下面parse_detail,提取详细页的内容
yield scrapy.Request(item["href"],callback=self.parse_detail,meta={"item":item})
#翻页
#获取url地址
next_url = response.xpath("//a[text()='>']/@href").extract_first()
#如果下一页url地址不为空,进入下一页连接
if next_url is not None:
yield scrapy.Request(next_url,callback=self.parse)
#处理详情页
def parse_detail(self,response):
#item接收meta传过来的item,在item字典里继续为item添加内容
item = response.meta["item"]
#拿到详细页的内容
item["content"] = response.xpath("//div[@class='c1 text14_2']//text()").extract()
#拿到详细页的图片地址
item["content_img"] = response.xpath("//div[@class='c1 text14_2']//img/@src").extract()
#给图片前面加上http://wz.sun0769.com
item["content_img"] = ["http://wz.sun0769.com" + i for i in item["content_img"]]
#把item传给pipeline
yield item
items(存储爬取字段)
import scrapy
#scrapy.Item是一个字典
class TencentItem(scrapy.Item):
#scrapy.Field()是一个字典
url = scrapy.Field()
name = scrapy.Field()
使用pipeline(管道)
from demo1 import settings
import pymongo
class Demo1Pipeline(object):
def __init__(self):
#连接mongodb数据库(数据库地址,端口号,数据库)
client = pymongo.MongoClient(host=settings.MONGODB_HOST, port=settings.MONGODB_PORT)
#选择数据库和集合
self.db = client[settings.MONGODB_DBNAME][settings.MONGODB_DOCNAME]
def process_item(self, item, spider):
data = dict(item)
self.db.insert(data)
#完成pipeline代码后,需要在setting中设置开启
ITEM_PIPELINES = {
#开启管道,可以设置多个管道,'管道地址数值':越小越先执行
'mySpider.pipelines.MyspiderPipeline': 300,
}
# MONGODB 主机环回地址127.0.0.1
MONGODB_HOST = '127.0.0.1'
# 端口号,默认是27017
MONGODB_PORT = 27017
# 设置数据库名称
MONGODB_DBNAME = 'DouBan'
# 存放本次数据的表名称
MONGODB_DOCNAME = 'DouBanMovies'
注意
- pipeline中process_item方法名不能修改,修改会报错
- pipeline(管道)可以有多个
- 设置了pipelines必须开启管道,权重越小优先级越高
把数据保存到mongodb中
#导入mongodb的包
from pymongo import MongoClient
#实例化client,建立连接
client = MongoClient(host='127.0.0.1',port = 27017)
#选择数据库和集合
collection = client["tencent"]["hr"]
class TencentPipeline(object):
def process_item(self, item, spider):
#传过来的数据是对象,把item转化为字典
item = dict(item)
#把数据存入mongodb数据库
collection.insert(item)
print(item)
return item