安装环境
pip install scrapy
发现Twisted版本不匹配
卸载pip uninstall Twisted
安装
pip install Twisted==22.10.0
新建scrapy项目
scrapy startproject 项目名
注意:项目名称不允许使用数字开头,也不能包含中文
eg: scrapy startproject scrapy_baidu_01
创建爬虫文件
要在spiders文件夹中去创建爬虫文件
切换路径:cd .\scrapy_baidu_01\scrapy_baidu_01\spiders\
scrapy genspider 爬虫文件的名字 要爬取网页
scrapy genspider baidu www.baidu.com
import scrapy
class BaiduSpider(scrapy.Spider):
# 爬虫的名字 用于运行爬虫的时候 使用的值
name = "baidu"
# 允许访问的域名
allowed_domains = ["www.baidu.com"]
# 起始的url地址 指的是第一次要访问的域名
start_urls = ["https://www.baidu.com"]
def parse(self, response):
pass
注意反爬:把这行代码注释掉settings.py
# ROBOTSTXT_OBEY = True(注释掉改行,不遵守robots协议,通常不用遵守)
运行爬虫代码
scrapy crawl baidu
项目结构
汽车之家案例
import scrapy
class CarSpider(scrapy.Spider):
name = "car"
allowed_domains = ["www.autohome.com.cn"]
start_urls = ["https://www.autohome.com.cn/price/brandid_15"]
def parse(self, response):
name_list = response.xpath('//div[@class="tw-mt-1 tw-px-4"]/a/text()')
price_list = response.xpath('//div[@class="tw-mt-1 tw-px-4"]/p/text()')
for i in range(len(name_list)):
name = name_list[i].extract()
price = price_list[i].extract()
print(name, price)
scrapy工作原理
当当网爬取数据
管道封装、开启多条管道、多页下载
items.py
import scrapy
class ScrapyDangdang04Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 图片
src = scrapy.Field()
# 名称
name = scrapy.Field()
# 价格
price = scrapy.Field()
# pass
pipelines.py
# 解决文件频繁打开的场景
# 如果想使用管道的话,就必须在settings.xml开启管道
class ScrapyDangdang04Pipeline:
def open_spider(self, spider):
# 使用w模式就行
# 因为只打开但没关
self.fp = open('book.json', 'w', encoding='utf-8')
# item就是yield后面的对象book
def process_item(self, item, spider):
# (1)write方法里面需要是字符串
# (2)w模式 会每一个对象都打开一次文件 覆盖之前的内容
# (3)所以使用a模式追加模式,不推荐
# with open('book.json', 'w', encoding='utf-8') as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
def close_spider(self, spider):
self.fp.close()
import urllib.request
# 多条管道开启
# 在settings.py开启管道
class DangDangDownloadPineline:
def process_item(self, item, spider):
url = 'http:' + item.get('src')
filename = './books/' + item.get('name') + '.jpg'
urllib.request.urlretrieve(url=url, filename=filename)
return item
settings.py
ITEM_PIPELINES = {
# 管道可以有多个 管道有优先级 值越小 优先级越高 优先级范围0~1000
"scrapy_dangdang_04.pipelines.ScrapyDangdang04Pipeline": 300,
"scrapy_dangdang_04.pipelines.DangDangDownloadPineline": 301,
}
dang.py
import scrapy
from scrapy_dangdang_04.items import ScrapyDangdang04Item
class DangSpider(scrapy.Spider):
name = "dang"
# 一般情况下,我们要调整domains范围,只写域名就可以了
allowed_domains = ["category.dangdang.com"]
start_urls = ["https://category.dangdang.com/cp01.01.02.00.00.00.html"]
# 多页下载数据 初始化url
base_url = 'https://category.dangdang.com/pg'
page = 1
def parse(self, response):
# pipelines管道
# items下载数据
# src=//ul[@id="component_59"]//li//img/@src
# alt=//ul[@id="component_59"]//li//img/@alt
# price=//ul[@id="component_59"]//li//p[@class="price"]//span[1]/text()
# 所有selector对象都可以再次调用xpath方法
li_list = response.xpath('//ul[@id="component_59"]//li')
for li in li_list:
# 图片做了懒加载
# 需要将src改为data-original
src = li.xpath('.//img