Enseñarle cómo usar el marco del rastreador Scrapy para rastrear los datos del foro de alimentos y almacenarlos en la base de datos.

    Hola a todos, esta es la primera vez que escribo un artículo sobre este tipo de proyecto para compartir. Puede ser muy acuoso e incompleto, y debe haber algunos errores. Espero que puedan darnos sugerencias en los comentarios. ¡Gracias!

I. Introducción

Un rastreador web (también conocido como araña web o robot web) es un programa o script que rastrea automáticamente información en la World Wide Web de acuerdo con ciertas reglas. Otros nombres menos utilizados son hormigas, indexación automática, simuladores o gusanos. ------ Enciclopedia de Baidu

    En términos humanos, los rastreadores se utilizan para obtener cantidades masivas de datos de manera regular, y luego procesarlos y usarlos. Es una de las condiciones de apoyo necesarias en big data, finanzas, aprendizaje automático, etc.

    En la actualidad, en las ciudades de primer nivel, el salario y el trato de los rastreadores son relativamente objetivos. Los ascensos posteriores a ingenieros de rastreadores intermedios y superiores, analistas de datos y puestos de desarrollo de big data son todas buenas transiciones.

 

2. Objetivos del proyecto

    El proyecto presentado aquí no tiene por qué ser demasiado complicado. El objetivo final es rastrear cada comentario de la publicación en la base de datos y actualizar los datos, evitar el rastreo repetido, anti-rastreo y otras medidas.

 

3. Preparación del proyecto

Esta parte presenta principalmente las herramientas utilizadas en este artículo, las bibliotecas involucradas, las páginas web y otra información, etc.

Software: PyCharm

Bibliotecas necesarias: Scrapy, selenium, pymongo, user_agent, datetime

Sitio web de destino:

http://bbs.foodmate.net

Plug-in: chromedriver (la versión debe ser correcta)

 

Cuatro, análisis de proyectos

1. Determine la estructura del sitio web de rastreo.

    En resumen: determine el método de carga del sitio web, cómo ingresar correctamente la publicación para capturar los datos nivel por nivel, qué formato usar para guardar los datos, etc.

    En segundo lugar, observar la estructura jerárquica del sitio web, es decir, cómo ir entrando poco a poco en la página del post según las secciones, esto es muy importante para esta tarea del crawler, y también es la parte principal de la escritura de código.

 

2. ¿Cómo elegir la forma correcta de rastrear datos?

    Actualmente, los métodos de rastreador que conozco son los siguientes (incompletos, pero de uso más común):

    1) Marco de solicitud: esta biblioteca http se puede usar para rastrear los datos requeridos de manera flexible, simple pero el proceso es un poco engorroso y se puede usar con herramientas de captura de paquetes para obtener datos. Pero debe determinar los encabezados y los parámetros de solicitud correspondientes; de lo contrario, los datos no se pueden obtener; una gran cantidad de rastreo de aplicaciones, rastreo de imágenes y videos, rastreo y detención, relativamente ligero y flexible, y alta concurrencia y despliegue distribuido también son muy flexibles , y las funciones pueden ser una realización más buena.

    2) Scrapy framework: se puede decir que scrapy framework es el más utilizado y el mejor framework de rastreadores para rastreadores. Tiene muchas ventajas: scrapy es asíncrono; utiliza xpath más legible en lugar de regular; potentes estadísticas y sistema de registro; en Al mismo tiempo, rastrear en diferentes URL; admite el modo de shell para facilitar la depuración independiente; admite la escritura de middleware para facilitar la escritura de algunos filtros unificados; se puede almacenar en la base de datos a través de una canalización, etc. Este es también el marco que se presentará en este artículo (combinado con la biblioteca de selenio).

 

Cinco, realización del proyecto

1. El primer paso: determinar el tipo de sitio web

    Primero, explique qué significa y qué sitio web buscar. En primer lugar, debe ver el método de carga del sitio web, ya sea carga estática, carga dinámica (carga js) u otros métodos; los diferentes métodos de carga requieren diferentes formas de lidiar con ello. Luego, observamos que el sitio web se rastreó hoy y descubrimos que este es un foro cronológico. Primero supusimos que era un sitio web cargado estáticamente; abrimos el complemento para organizar la carga de js, como se muestra en la siguiente figura.

Imagen

    Después de la actualización, se descubre que de hecho es un sitio web estático (si se puede cargar normalmente, básicamente se carga estáticamente).

 

2. Paso 2: determinar la jerarquía

    En segundo lugar, el sitio web que queremos rastrear hoy es el sitio web del foro de alimentos, que es un sitio web cargado estáticamente. Ya lo hemos entendido durante el análisis anterior, y luego la estructura jerárquica:

 

Imagen

    Probablemente el proceso anterior, hay un total de tres niveles de acceso progresivo, y luego llega a la página de publicación, como se muestra en la figura siguiente.

Imagen

Mucha gente aprende Python y no sabe por dónde empezar.
Muchas personas aprenden Python y después de dominar la gramática básica, no saben dónde encontrar casos para comenzar.
Muchas personas que han realizado estudios de casos no saben cómo adquirir conocimientos más avanzados.
Entonces, para estos tres tipos de personas, les proporcionaré una buena plataforma de aprendizaje, ¡gratis para recibir tutoriales en video, libros electrónicos y el código fuente del curso!
Grupo QQ: 721195303

Parte de la visualización del código:

    Interfaz de primer nivel:

def parse(self, response):
    self.logger.info("已进入网页!")
    self.logger.info("正在获取版块列表!")
    column_path_list = response.css('#ct > div.mn > div:nth-child(2) > div')[:-1]
    for column_path in column_path_list:
        col_paths = column_path.css('div > table > tbody > tr > td > div > a').xpath('@href').extract()
        for path in col_paths:
            block_url = response.urljoin(path)
            yield scrapy.Request(
                url=block_url,
                callback=self.get_next_path,
            )

    Interfaz secundaria:

def get_next_path(self, response):
    self.logger.info("已进入版块!")
    self.logger.info("正在获取文章列表!")
    if response.url == 'http://www.foodmate.net/know/':
        pass
    else:
        try:
            nums = response.css('#fd_page_bottom > div > label > span::text').extract_first().split(' ')[-2]
        except:
            nums = 1
        for num in range(1, int(nums) + 1):
            tbody_list = response.css('#threadlisttableid > tbody')
            for tbody in tbody_list:
                if 'normalthread' in str(tbody):
                    item = LunTanItem()
                    item['article_url'] = response.urljoin(
                        tbody.css('* > tr > th > a.s.xst').xpath('@href').extract_first())
                    item['type'] = response.css(
                        '#ct > div > div.bm.bml.pbn > div.bm_h.cl > h1 > a::text').extract_first()
                    item['title'] = tbody.css('* > tr > th > a.s.xst::text').extract_first()
                    item['spider_type'] = "论坛"
                    item['source'] = "食品论坛"
                    if item['article_url'] != 'http://bbs.foodmate.net/':
                        yield scrapy.Request(
                            url=item['article_url'],
                            callback=self.get_data,
                            meta={'item': item, 'content_info': []}
                        )
        try:
            callback_url = response.css('#fd_page_bottom > div > a.nxt').xpath('@href').extract_first()
            callback_url = response.urljoin(callback_url)
            yield scrapy.Request(
                url=callback_url,
                callback=self.get_next_path,
            )
        except IndexError:
            pass

    Interfaz de tres niveles:

def get_data(self, response):
    self.logger.info("正在爬取论坛数据!")
    item = response.meta['item']
    content_list = []
    divs = response.xpath('//*[@id="postlist"]/div')
    user_name = response.css('div > div.pi > div:nth-child(1) > a::text').extract()
    publish_time = response.css('div.authi > em::text').extract()
    floor = divs.css('* strong> a> em::text').extract()
    s_id = divs.xpath('@id').extract()
    for i in range(len(divs) - 1):
        content = ''
        try:

            strong = response.css('#postmessage_' + s_id[i].split('_')[-1] + '').xpath('string(.)').extract()
            for s in strong:
                content += s.split(';')[-1].lstrip('\r\n')
            datas = dict(content=content,  # 内容
                         reply_id=0,  # 回复的楼层,默认0
                         user_name=user_name[i],  # ⽤户名
                         publish_time=publish_time[i].split('于 ')[-1],  # %Y-%m-%d %H:%M:%S'
                         id='#' + floor[i],  # 楼层
                         )
            content_list.append(datas)
        except IndexError:
            pass
    item['content_info'] = response.meta['content_info']
    item['scrawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    item['content_info'] += content_list

    data_url = response.css('#ct > div.pgbtn > a').xpath('@href').extract_first()
    if data_url != None:
        data_url = response.urljoin(data_url)
        yield scrapy.Request(
            url=data_url,
            callback=self.get_data,
            meta={'item': item, 'content_info': item['content_info']}
        )
    else:
        item['scrawl_time'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        self.logger.info("正在存储!")
        print('储存成功')
        yield item

 

3. Paso 3: determinar el método de rastreo

    Debido a que es una página web estática, primero decidí usar el marco scrapy para obtener datos directamente y, a través de la prueba preliminar, se descubrió que el método era realmente factible. Sin embargo, en ese momento, yo era joven, frívolo y subestimado. las medidas de protección del sitio web. Debido a la paciencia limitada, no se agregó ningún temporizador para limitar el rastreo. La velocidad hizo que el sitio web me restringiera y el sitio web cambió de una página web cargada estáticamente a un algoritmo de verificación de página web de carga dinámica antes de ingresar al página web, el acceso directo será rechazado por el fondo.

    Pero, ¿cómo podría ser mi ingenio este tipo de problema? Después de un corto período de reflexión (1 día), cambié el esquema al método de scrapy framework + biblioteca de selenio, y llamé al controlador cromado para simular la visita al sitio web. cargado, no sería rastreado. Eso es todo. El seguimiento demuestra que este método es realmente factible y eficiente.

    La parte de implementación del código es la siguiente:

def process_request(self, request, spider):
    chrome_options = Options()
    chrome_options.add_argument('--headless')  # 使用无头谷歌浏览器模式
    chrome_options.add_argument('--disable-gpu')
    chrome_options.add_argument('--no-sandbox')
    # 指定谷歌浏览器路径
    self.driver = webdriver.Chrome(chrome_options=chrome_options,
                                   executable_path='E:/pycharm/workspace/爬虫/scrapy/chromedriver')
    if request.url != 'http://bbs.foodmate.net/':
        self.driver.get(request.url)
        html = self.driver.page_source
        time.sleep(1)
        self.driver.quit()
        return scrapy.http.HtmlResponse(url=request.url, body=html.encode('utf-8'), encoding='utf-8',
                                        request=request)

 

4. Paso 4: determinar el formato de almacenamiento de los datos rastreados

    No hace falta decir que esta parte, de acuerdo con sus propias necesidades, establezca el formato de datos que se debe rastrear en items.py. Simplemente use este formato para guardar en el proyecto:

class LunTanItem(scrapy.Item):
    """
        论坛字段
    """
    title = Field()  # str: 字符类型 | 论坛标题
    content_info = Field()  # str: list类型 | 类型list: [LunTanContentInfoItem1, LunTanContentInfoItem2]
    article_url = Field()  # str: url | 文章链接
    scrawl_time = Field()  # str: 时间格式 参照如下格式 2019-08-01 10:20:00 | 数据爬取时间
    source = Field()  # str: 字符类型 | 论坛名称 eg: 未名BBS, 水木社区, 天涯论坛
    type = Field()  # str: 字符类型 | 板块类型 eg: '财经', '体育', '社会'
    spider_type = Field()  # str: forum | 只能写 'forum'

 

5. Paso 5: Confirme para guardar la base de datos.

    La base de datos elegida para este proyecto es mongodb. Debido a que es una base de datos no relacional, las ventajas son obvias y los requisitos de formato no son tan altos, y los datos multidimensionales se pueden almacenar de manera flexible. Por lo general, es la base de datos preferida por los rastreadores (no me digas redis, lo usaré si lo sé, principalmente no)

    Código:

import pymongo

class FMPipeline():
    def __init__(self):
        super(FMPipeline, self).__init__()
        # client = pymongo.MongoClient('139.217.92.75')
        client = pymongo.MongoClient('localhost')
        db = client.scrapy_FM
        self.collection = db.FM

    def process_item(self, item, spider):
        query = {
            'article_url': item['article_url']
        }
        self.collection.update_one(query, {"$set": dict(item)}, upsert=True)
        return item

    En este momento, algunos amigos inteligentes preguntarán: ¿Qué pasa si los mismos datos se rastrean dos veces? (En otras palabras, es la función de verificación de duplicados)

    No pensé en esta pregunta antes. Más tarde, me enteré cuando les pregunté a los grandes. Esto se hizo cuando guardamos los datos, solo esta oración:

query = {
    'article_url': item['article_url']
}
self.collection.update_one(query, {"$set": dict(item)}, upsert=True)

    Determinar si hay datos duplicados rastreando a través del enlace de la publicación, si está duplicado se puede entender que lo cubre, por lo que también se pueden actualizar los datos.

 

6. Otros entornos

    Los problemas como subprocesos múltiples, encabezados, secuencia de transmisión de canalización, etc., se configuran en el archivo settings.py. Para obtener más detalles, consulte el proyecto del editor para verlo. No entraré en detalles aquí.

 

Siete, visualización de efectos

    1. Haga clic en Ejecutar y el resultado se mostrará en la consola, como se muestra en la siguiente figura.

Imagen

Imagen

    2. En el medio, habrá tareas de rastreo que acumularán muchas publicaciones en la cola, y luego procesamiento de múltiples subprocesos. Establecí 16 subprocesos, y la velocidad sigue siendo muy impresionante.

Imagen

    3. Visualización de datos de la base de datos:

Imagen

    El content_info almacena todos los comentarios de cada publicación y la información pública de los usuarios relacionados.

 

8. Resumen

    1. Este artículo presenta principalmente el proceso de recopilación y almacenamiento de datos de los sitios web de alimentos y explica en detalle cómo analizar la estructura de la página web, las estrategias de rastreo, los tipos de sitios web, las relaciones jerárquicas, los métodos de rastreo y los procesos de almacenamiento de datos, y finalmente realizar cada comentario sobre el publicar Rastreo en la base de datos, y para poder actualizar los datos para evitar el rastreo repetido, anti-rastreo, etc., los productos secos están llenos.

    2. En general, este proyecto no es particularmente difícil. Siempre que la idea sea correcta y se encuentren las reglas de los datos, se puede decir que es fácil levantarse. La dificultad es que el proceso no se ha completado antes, y con esta introducción relativamente acuática, espero poder ayudarlos, será mi mayor honor.

    3. Cuando te encuentres con problemas, lo primero en lo que debes pensar no es en preguntar a colegas, amigos, profesores, sino en ir a Google y Baidu para ver si hay situaciones similares y ver las experiencias de otras personas. Debes aprender a descubrir, piensa y resuelve los problemas por ti mismo. Después de eso, el trabajo es muy útil (antes me han dicho que no he dejado mis días escolares, es decir, me gusta preguntar a mis compañeros). Después de comprobar cierta información en línea, todavía no tengo ni idea, y luego pregunte a otros, otros estarán más dispuestos a ayudar a los suyos ~

 

Todavía quiero recomendar el grupo de aprendizaje de Python que construí yo mismo : 721195303 , todos los cuales están aprendiendo Python. Si quieres aprender o estás aprendiendo Python, puedes unirte. Todos son parte del desarrollo de software y comparten productos secos de de vez en cuando (solo relacionado con el desarrollo de software de Python), incluida una copia de los últimos materiales avanzados de Python y la enseñanza basada en cero compilada por mí en 2021. ¡Bienvenidos amigos que están en un nivel avanzado e interesados ​​en Python para que se unan!

Supongo que te gusta

Origin blog.csdn.net/pyjishu/article/details/114652698
Recomendado
Clasificación