Directorio de artículos
- Índice de artículos de la serie
- 1. Introducción a scrapy
- 2. Uso básico de scrapy
-
- 1. Crea un proyecto
- 2. Cree un archivo de rastreo
- 3. (Adjunto) Composición del proyecto
- 4. Ejecute el código del rastreador.
- 5. Atributos y métodos de respuesta
- 6. Combate práctico: obtenga el contenido del botón [Baidu Click] de Baidu
- 7. Combate práctico: Obtenga la lista de precios de automóviles Autohome
- 3. Utilice cáscara raspada
- 4. Combate práctico: obtención de datos de productos de Dangdang.com
- 5. Combate práctico: Obtención de datos de diferentes páginas de Movie Paradise
- 6. Combate práctico: utilice CrawlSpider para obtener datos de Dudu.com
- 7. Combate práctico: envío de solicitud de publicación.
Índice de artículos de la serie
Conceptos básicos del rastreador de Python (1): explicación detallada del uso de la biblioteca urllib.
Conceptos básicos del rastreador de Python (2): uso de xpath y jsonpath para analizar datos rastreados.
Conceptos básicos del rastreador de Python (3): uso de Selenium para cargar páginas web dinámicamente.
Conceptos básicos del rastreador de Python (4) : Más conveniente para usar los conceptos básicos del rastreador de Python de la biblioteca de solicitudes
(5): uso del marco scrapy
1. Introducción a scrapy
1. ¿Qué es scrapy?
Scrapy es un marco de aplicación escrito para rastrear datos de páginas web y extraer datos estructurados. El marco está encapsulado e incluye solicitudes (programación y procesamiento asincrónicos), descargador (descargador multiproceso), analizador (selector) y retorcido (procesamiento asincrónico), etc. Para el rastreo de contenido de sitios web, su velocidad es muy rápida.
2. instalación deficiente
# 进入到python安装目录的Scripts目录
d:
cd D:\python\Scripts
# 安装 可以使用国内源
pip install scrapy
3. Composición de arquitectura scrapy
(1) Motor: se ejecuta automáticamente, no es necesario prestar atención, organizará automáticamente todos los objetos solicitados y los distribuirá a los descargadores.
(2) Descargador: después de obtener el objeto de solicitud del motor, solicite los datos.
(3) Arañas: la clase araña define cómo rastrear un determinado (o determinado) sitio web. Incluye acciones de rastreo (por ejemplo: seguir enlaces) y cómo extraer datos estructurados del contenido de las páginas web (elementos de rastreo). En otras palabras, Spider es el lugar donde se definen las acciones de rastreo y se analiza una página web.
(4) Programador: tiene sus propias reglas de programación, no es necesario prestarle atención.
(5) Canalización (canalización de elementos): la canalización que finalmente procesa los datos reservará interfaces para que procesemos los datos. Una vez que el artículo se recopila en Spider, se pasará a la canalización de artículos y algunos componentes realizarán el procesamiento del artículo en un orden determinado. Cada componente de la canalización de elementos es una clase de Python que implementa métodos simples. Reciben el elemento y realizan algunas acciones a través de él. También deciden si el elemento continúa pasando por la canalización o se descarta sin procesar.
Las siguientes son algunas aplicaciones típicas de la canalización de elementos:
(1) Limpiar datos HTML, (2) Verificar los datos rastreados (verificar que el elemento contenga ciertos campos), (3) Verificar duplicaciones (y descartar), (4) Convertir los resultados rastreados se guardan en la base de datos.
4. Cómo funciona Scrapy
arañas->programador (programador)->motor scrapy (motor)->descargador (descargador)->Descargar de Internet->
Datos descargados del motor a arañas->Análisis de datos a través del motor xpath->Usar canalización para almacenamiento de datos
2. Uso básico de scrapy
1. Crea un proyecto
Ingrese al directorio del proyecto y abra cmd:
# 创建scrapy_test_001项目,项目名不能以数字、汉字开头
scrapy startproject scrapy_test
2. Cree un archivo de rastreo
Para crear un archivo de rastreador en la carpeta de arañas
# cd 项目的名字\项目的名字\spiders
cd scrapy_test\scrapy_test\spiders
Cree un archivo de rastreador. Tenga en cuenta que no es necesario agregar el protocolo http:
# scrapy genspider 爬虫文件的名字 要爬取网页
scrapy genspider baidu www.baidu.com
En este momento, se generará un baidu.py en el directorio de arañas:
Echemos un vistazo al contenido de baidu.py:
import scrapy
class BaiduSpider(scrapy.Spider):
# 爬虫的名字 用于运行爬虫的时候 使用的值
name = "baidu"
# 允许访问的域名
allowed_domains = ["www.baidu.com"]
# 起始的url地址 指的是第一次要访问的域名
start_urls = ["https://www.baidu.com"]
# 是执行了start_urls之后 执行的方法 方法中的response 就是返回的那个对象
# 相当于 response = urllib.request.urlopen()
# response = requests.get()
def parse(self, response):
pass
Más tarde, podemos procesar la respuesta en el método de análisis, que es el resultado final del rastreo.
3. (Adjunto) Composición del proyecto
4. Ejecute el código del rastreador.
(1) Modificar baidu.py
En el método de análisis, personalice la salida:
def parse(self,response):
print('输出正确!')
En el directorio de arañas, ejecute el siguiente comando para ejecutar el código del rastreador:
# scrapy crawl 爬虫的名字
scrapy crawl baidu
Se generará una gran cantidad de contenido, pero no imprimimos nada.
(2) archivo de robots
En la consola, está impreso el protocolo del robot de Baidu:
Cada sitio web tendrá un acuerdo de caballeros sobre robots, que define lo que no se permite rastrear. Veamos los robots de Baidu:
https://www.baidu.com/robots.txt
En el archivo settings.py del proyecto, el valor predeterminado es ROBOTSTXT_OBEY=True, lo que significa seguir este acuerdo de caballeros.
Sólo necesitamos comentar esta línea:
en este punto ejecutaremos el código del rastreador:
# scrapy crawl 爬虫的名字
scrapy crawl baidu
En este momento, en la línea de comando, se imprimirá nuestra oración personalizada.
5. Atributos y métodos de respuesta
Response.xpath (xpath_expression): selecciona y extrae datos según la expresión XPath.
Response.css (css_expression): selecciona y extrae datos según los selectores CSS.
respuesta.follow (url): crea una nueva solicitud basada en la URL proporcionada y continúa procesando a través del método de devolución de llamada.
respuesta.url: devuelve la URL de la respuesta actual.
respuesta.status: Devuelve el código de estado de la respuesta actual.
Response.headers: devuelve la información del encabezado de la respuesta actual.
respuesta.cuerpo: devuelve el contenido binario sin formato de la respuesta actual.
respuesta.texto: devuelve el contenido de texto de la respuesta actual.
Response.css('a::attr(href)').getall(): utilice el selector CSS para extraer todos los valores de atributos de elementos coincidentes.
Response.xpath('//a/@href').extract(): utilice expresiones XPath para extraer todos los valores de atributos de elementos coincidentes.
6. Combate práctico: obtenga el contenido del botón [Baidu Click] de Baidu
def parse(self, response):
print('=====================')
input = response.xpath('//input[@id="su"]/@value')[0]
print(input.extract()) # 百度一下
print('=====================')
7. Combate práctico: Obtenga la lista de precios de automóviles Autohome
import scrapy
class CarSpider(scrapy.Spider):
name = 'car'
allowed_domains = ['https://car.autohome.com.cn/price/brand-15.html']
start_urls = ['https://car.autohome.com.cn/price/brand-15.html']
def parse(self, response):
print('=======================')
name_list = response.xpath('//div[@class="main-title"]/a/text()')
price_list = response.xpath('//div[@class="main-lever"]//span/span/text()')
for i in range(len(name_list)):
name = name_list[i].extract()
price = price_list[i].extract()
print(name,price)
print('=======================')
3. Utilice cáscara raspada
1. ¿Qué es la concha raspada?
La terminal scrapy es una terminal interactiva para que pueda intentar depurar su código de rastreo sin iniciar la araña. Está diseñado para probar código que extrae datos, pero puede usarlo como un terminal Python normal y probar cualquier código Python en él.
Este terminal se utiliza para probar expresiones xPath o CSS para ver cómo funcionan y extraer datos de páginas web rastreadas. Al escribir su araña, la terminal brinda la capacidad de probar interactivamente su código de expresión, eliminando el problema de ejecutar la araña después de cada modificación. Una vez que se familiarice con la terminal scrapy, descubrirá que desempeña un papel muy importante en el desarrollo y depuración de arañas.
2. Instale ipython (opcional)
# 进入到python安装目录的Scripts目录
d:
cd D:\python\Scripts
# 安装 可以使用国内源
pip install ipython
Si IPython está instalado, el terminal scrapy utilizará IPython (en lugar del terminal Python estándar). El terminal IPython es más potente que otros y proporciona autocompletado inteligente, salida resaltada y otras funciones.
Uso: Ingrese ipython directamente en la línea de comando y la nueva ventana de comando tendrá su propio resaltado y autocompletado:
3. Utilice cáscara raspada
# 直接在window的终端中输入scrapy shell 域名
# 直接在命令终端(不需要进入python或者ipython终端),执行完毕之后,自动进入ipython终端
scrapy shell www.baidu.com
El objeto de respuesta se puede obtener y depurar directamente aquí.
4. Combate práctico: obtención de datos de productos de Dangdang.com
1. Inicializar proyecto
# 在自定义目录中创建项目
scrapy startproject scrapy_dangdang
# 创建爬虫文件
# cd 项目的名字\项目的名字\spiders
cd scrapy_dangdang\scrapy_dangdang\spiders
# scrapy genspider 爬虫文件的名字 要爬取网页
# 中国古典小说网址:http://category.dangdang.com/cp01.03.32.00.00.00.html
scrapy genspider dang http://category.dangdang.com/cp01.03.32.00.00.00.html
# 运行
scrapy crawl dang
2. Definir archivo de artículo
En item.py generado automáticamente por el proyecto, defina el formato de datos que se rastreará:
import scrapy
class ScrapyDangdangItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 通俗的说就是你要下载的数据都有什么,固定写法:scrapy.Field()
# 图片
src = scrapy.Field()
# 名字
name = scrapy.Field()
# 价格
price = scrapy.Field()
3. Rastrear imágenes, nombres y precios.
Primero analicemos el xpath de estos tres:
Obtenga el xpath de la imagen: //ul[@id="component_59"]/li/a/img/@src
debido a que la imagen se carga de forma diferida, se deben obtener los atributos de la imagen data-original
.
Obtener el xpath del título: //ul[@id="component_59"]/li/p[@class="name"]/a/@title
Obtener el xpath del precio://ul[@id="component_59"]/li/p[@class="price"]/span[1]/text()
import scrapy
class DangSpider(scrapy.Spider):
name = "dang"
allowed_domains = ["category.dangdang.com"]
start_urls = ["http://category.dangdang.com/cp01.03.32.00.00.00.html"]
def parse(self, response):
# src = //ul[@id="component_59"]/li/a/img/@src
# name = //ul[@id="component_59"]/li/p[@class="name"]/a/@title
# price = //ul[@id="component_59"]/li/p[@class="price"]/span[1]/text()
# 所有的seletor的对象 都可以再次调用xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
src = li.xpath('./a/img/@data-original').extract_first()
# 第一张图片和其他的图片的标签的属性是不一样的
# 第一张图片的src是可以使用的 其他的图片的地址是data-original
if src:
src = src
else:
src = li.xpath('./a/img/@src').extract_first()
name = li.xpath('./p[@class="name"]/a/@title').extract_first()
price = li.xpath('./p[@class="price"]/span[1]/text()').extract_first()
# 拿到所有信息
print(src + name + price)
4. Embalaje de tuberías
(1) Familiarizado con el rendimiento
Una función vinculada ya no es una función ordinaria, sino un generador que puede usarse para iteración.
rendimiento es una palabra clave similar a retorno. Cuando la iteración encuentra rendimiento, devuelve el valor después del rendimiento (lado derecho). El punto es: en la siguiente iteración, la ejecución comienza desde el código (siguiente línea) después del rendimiento encontrado por el iterador anterior.
Comprensión simple: rendimiento significa que retorno devuelve un valor y recuerda la posición devuelta, y la siguiente iteración comenzará desde esta posición (siguiente línea).
(2) Construya el objeto del artículo y entréguelo a la tubería.
Arriba hemos obtenido la imagen, el nombre y el precio, continuamos construyendo el objeto del artículo en el método de análisis y lo entregamos a la canalización:
from scrapy_dangdang.items import ScrapyDangdangItem
# 构造item对象
book = ScrapyDangdangItem(src=src,name=name,price=price)
# 获取一个book就将book交给pipelines
yield book
(3) Habilitar canalización en settings.py
Puede haber muchas canalizaciones, por lo que las canalizaciones tienen prioridades. El rango de prioridad es de 1 a 1000. Cuanto menor sea el valor, mayor será la prioridad.
ITEM_PIPELINES = {
# 管道可以有很多个 那么管道是有优先级的 优先级的范围是1到1000 值越小优先级越高
"scrapy_dangdang.pipelines.ScrapyDangdangPipeline": 300,
}
(4) Editar canalización.py
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html
# useful for handling different item types with a single interface
from itemadapter import ItemAdapter
# 如果想使用管道的话 那么就必须在settings中开启管道
class ScrapyDangdangPipeline:
# 在爬虫文件开始的之前就执行的一个方法 :open_spider
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# 执行过程:process_item
# item就是yield后面的book对象
def process_item(self, item, spider):
# 以下这种模式不推荐 因为每传递过来一个对象 那么就打开一次文件 对文件的操作过于频繁
# # (1) write方法必须要写一个字符串 而不能是其他的对象
# # (2) w模式 会每一个对象都打开一次文件 覆盖之前的内容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
self.fp.write('\n')
return item
# 在爬虫文件执行完之后 执行的方法 : close_spider
def close_spider(self,spider):
self.fp.close()
(5) Ejecute y vea el archivo json escrito
scrapy crawl dang
5. Uso de múltiples tuberías
(1)pipelines.py define la clase de canalización
Se pueden definir varias clases en pipelines.py, simplemente escríbalas directamente.
Hay tres métodos predeterminados en la clase que se pueden usar directamente.
import urllib.request
class ScrapyDangdangDownloadPipeline:
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
(2) settings.py abre la canalización
ITEM_PIPELINES = {
# 管道可以有很多个 那么管道是有优先级的 优先级的范围是1到1000 值越小优先级越高
"scrapy_dangdang.pipelines.ScrapyDangdangPipeline": 300,
'scrapy_dangdang.pipelines.ScrapyDangdangDownloadPipeline':301
}
(5) Ejecute y vea las imágenes y los archivos json escritos.
Primero cree el directorio de libros en arañas.
# 执行
scrapy crawl dang
6. Obtenga varias páginas de datos
import scrapy
from scrapy_dangdang.items import ScrapyDangdangItem
class DangSpider(scrapy.Spider):
name = "dang"
allowed_domains = ["category.dangdang.com"]
start_urls = ["http://category.dangdang.com/cp01.03.32.00.00.00.html"]
base_url = 'http://category.dangdang.com/cp'
page = 1
def parse(self, response):
# 。。。省略
# 每一页的爬取的业务逻辑全都是一样的,所以我们只需要将执行的那个页的请求再次调用parse方法
# 就可以了
# http://category.dangdang.com/pg2-cp01.03.32.00.00.00.html
# http://category.dangdang.com/pg3-cp01.03.32.00.00.00.html
# http://category.dangdang.com/pg4-cp01.03.32.00.00.00.html
if self.page < 100:
self.page = self.page + 1
url = self.base_url + str(self.page) + '-cp01.03.32.00.00.00.html'
# 怎么去调用parse方法
# scrapy.Request就是scrpay的get请求
# url就是请求地址
# callback是你要执行的那个函数 注意不需要加()
yield scrapy.Request(url=url,callback=self.parse)
5. Combate práctico: Obtención de datos de diferentes páginas de Movie Paradise
1. Efecto
Obtenga Movie Paradise, el nombre de la película en la lista de la primera página:
luego haga clic en los detalles de la película y luego obtenga la imagen en los detalles de la segunda página:
2. Código central
código central mv.py
import scrapy
from scrapy_movie_099.items import ScrapyMovie099Item
class MvSpider(scrapy.Spider):
name = 'mv'
allowed_domains = ['www.dygod.net']
start_urls = ['https://www.dygod.net/html/gndy/china/index.html']
def parse(self, response):
# 要第一个的名字 和 第二页的图片
a_list = response.xpath('//div[@class="co_content8"]//td[2]//a[2]')
for a in a_list:
# 获取第一页的name 和 要点击的链接
name = a.xpath('./text()').extract_first()
href = a.xpath('./@href').extract_first()
# 第二页的地址是
url = 'https://www.dygod.net' + href
# 对第二页的链接发起访问 并将name参数传入
yield scrapy.Request(url=url,callback=self.parse_second,meta={
'name':name})
def parse_second(self,response):
# 注意 如果拿不到数据的情况下 一定检查你的xpath语法是否正确
src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
# 接受到请求的那个meta参数的值
name = response.meta['name']
movie = ScrapyMovie099Item(src=src,name=name)
yield movie
tuberías.py:
from itemadapter import ItemAdapter
class ScrapyMovie099Pipeline:
def open_spider(self,spider):
self.fp = open('movie.json','w',encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self,spider):
self.fp.close()
Abra la canalización en settings.py:
ITEM_PIPELINES = {
'scrapy_movie_099.pipelines.ScrapyMovie099Pipeline': 300,
}
6. Combate práctico: utilice CrawlSpider para obtener datos de Dudu.com
1. Introducción a CrawlSpider
CrawlSpider hereda de scrapy.Spider y puede definir reglas. Al analizar el contenido HTML, puede extraer enlaces específicos de acuerdo con las reglas de enlace y luego enviar solicitudes a estos enlaces.
Por lo tanto, si es necesario realizar un seguimiento del enlace, es decir, después de rastrear la página web, debe extraer el enlace y rastrearlo nuevamente, usar CrawlSpider es muy adecuado.
Sintaxis común para extraer enlaces :
extractor de enlaces, donde puede escribir reglas para extraer enlaces específicos:
scrapy.linkextractors.LinkExtractor(
allow = (), # 正则表达式,提取符合正则的链接
deny = (), # (不用)正则表达式 不提取符合正则的链接
allow_domains = (), # (不用)允许的域名
deny_domains = (), # (不用)不允许的域名
restrict_xpaths = (), # xpath,提取符合xpath规则的链接
restrict_css = () # 提取符合选择器规则的链接
)
# 使用实例
# 正则用法:
links = LinkExtractor(allow = r'list_23_\d+\.html')
# xpath:
links = LinkExtractor(restrict_xpaths = r'//div[@class="x"]')
# css用法:
links = LinkExtractor(restrict_css='.x')
# 提取链接
links.extract_links(response)
2. Crea un proyecto
# 创建项目:scrapy startproject 项目的名字
scrapy startproject readbook
# 创建爬虫文件
# cd 项目名字\项目名字\spiders
cd readbook/readbook/Spiders
# scrapy genspider -t crawl 爬虫文件的名字 爬取的域名
scrapy genspider -t crawl read www.dushu.com/book/1188_1.html
Descubrimos que el contenido de read.py era diferente al que teníamos antes:
3. Definir artículo
class ReadbookItem(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
src = scrapy.Field()
4. Extraer datos
leer.py:
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from readbook.items import ReadbookItem
class ReadSpider(CrawlSpider):
name = "read"
allowed_domains = ["www.dushu.com"]
# 注意,第一个url也要匹配规则!不然会跳过第一页
start_urls = ["https://www.dushu.com/book/1188_1.html"]
# 规则
rules = (Rule(LinkExtractor(allow=r"/book/1188_\d+.html"), callback="parse_item", follow=True),)
# 解析
def parse_item(self, response):
img_list = response.xpath('//div[@class="bookslist"]//img')
for img in img_list:
name = img.xpath('./@data-original').extract_first()
src = img.xpath('./@alt').extract_first()
book = ReadbookItem(name=name,src=src)
yield book
5. Definir canalización
# settings.py
ITEM_PIPELINES = {
"readbook.pipelines.ReadbookPipeline": 300,
}
# pipelines.py
from itemadapter import ItemAdapter
class ReadbookPipeline:
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self,spider):
self.fp.close()
6. Empezar
scrapy crawl read
Después de la ejecución, vea el archivo book.json.
7. Guardar en mysql
Instalar pymysql:
# 进入到python安装目录的Scripts目录
d:
cd D:\python\Scripts
# 安装 可以使用国内源
pip install pymysql
Agregar una canalización:
# settings.py
ITEM_PIPELINES = {
"readbook.pipelines.ReadbookPipeline": 300,
# MysqlPipeline
'readbook.pipelines.MysqlPipeline':301
}
# 参数中一个端口号 一个是字符集 都要注意
DB_HOST = '192.168.1.1'
# 端口号是一个整数
DB_PORT = 3306
DB_USER = 'root'
DB_PASSWROD = '123'
DB_NAME = 'spider01'
# utf-8的杠不允许写
DB_CHARSET = 'utf8'
tuberías.py:
# 加载settings文件
from scrapy.utils.project import get_project_settings
import pymysql
class MysqlPipeline:
def open_spider(self,spider):
settings = get_project_settings()
self.host = settings['DB_HOST']
self.port =settings['DB_PORT']
self.user =settings['DB_USER']
self.password =settings['DB_PASSWROD']
self.name =settings['DB_NAME']
self.charset =settings['DB_CHARSET']
self.connect()
def connect(self):
self.conn = pymysql.connect(
host=self.host,
port=self.port,
user=self.user,
password=self.password,
db=self.name,
charset=self.charset
)
self.cursor = self.conn.cursor()
def process_item(self, item, spider):
sql = 'insert into book(name,src) values("{}","{}")'.format(item['name'],item['src'])
# 执行sql语句
self.cursor.execute(sql)
# 提交
self.conn.commit()
return item
def close_spider(self,spider):
self.cursor.close()
self.conn.close()
7. Combate práctico: envío de solicitud de publicación.
Clave:
import scrapy
import json
class TestpostSpider(scrapy.Spider):
name = 'testpost'
allowed_domains = ['https://fanyi.baidu.com/sug']
# post请求 如果没有参数 那么这个请求将没有任何意义
# 所以start_urls 也没有用了
# parse方法也没有用了
# start_urls = ['https://fanyi.baidu.com/sug/']
#
# def parse(self, response):
# pass
# start_requests是一个固定方法
def start_requests(self):
url = 'https://fanyi.baidu.com/sug'
data = {
'kw': 'final'
}
yield scrapy.FormRequest(url=url,formdata=data,callback=self.parse_second)
def parse_second(self,response):
content = response.text
obj = json.loads(content,encoding='utf-8')
print(obj)