使用Scarpy框架爬取链家网站经纪人列表

简介

        在网络数据抓取和处理中,Scrapy是一个强大的工具,它能够简化爬虫的构建过程。本文将介绍如何使用Scrapy抓取链家网站的经纪人信息,并通过Python对这些信息进行处理。

 一、环境设置

安装 Python

确保您的计算机上安装了 Python。您可以在Python官方网站上下载并安装最新版本的 Python。

安装 pip

在安装 Python 时,通常会一并安装 pip,它是 Python 包管理工具。但如果您的 Python 版本较旧或者没有安装 pip,请根据您的操作系统安装 pip。

安装 Scrapy

使用 pip 安装 Scrapy。在命令行中执行以下命令:

pip install scrapy

这将安装最新版本的 Scrapy 爬虫框架。

安装 pymongo

要将爬取到的数据存储到 MongoDB 中,需要安装 pymongo 这个 Python MongoDB 客户端库。在命令行中执行以下命令:

pip install pymongo

安装 MongoDB

如果您尚未安装 MongoDB 数据库,您可以从MongoDB官方网站下载适用于您操作系统的版本并进行安装。

创建 MongoDB 数据库和集合

确保您已经在本地启动了 MongoDB 服务。然后使用以下命令连接到 MongoDB,并创建一个数据库和集合来存储爬取到的数据:

mongo

use pachong  # 创建名为 pachong 的数据库

db.createCollection("pachong")  # 在 pachong 数据库中创建名为 pachong 的集合
创建Scrapy项目
scrapy startproject lianjia    #创建lianjia项目,你也可以创建为其他名字
cd lianjia                     #移动到该pachong2目录下

创建爬虫文件

scrapy genspider lianjia  
#woaiwojia为爬虫文件名

得到以下文件目录即可

使用Scarpy框架爬取链家网站经纪人列表_第1张图片

二、观察待爬取页面

使用Scarpy框架爬取链家网站经纪人列表_第2张图片

查看待爬取的元素的位置,尝试使用xpath定位

使用xpath在线工具发现无法正常进行定位

使用Scarpy框架爬取链家网站经纪人列表_第3张图片

尝试使用css定位也失败,于是更换思路

三、更换思路

待爬取链接为“m”开头,所以尝试更换请求头为手机浏览器

 这是下载页面信息的代码:

import scrapy

class LianjiaSpider(scrapy.Spider):
    name = 'lianjia'
    allowed_domains = ['m.lianjia.com']
    start_urls = ['https://m.lianjia.com/bj/jingjiren/?page_size=15&_t=1&offset=15']

    custom_settings = {
        'USER_AGENT': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
    }

    def parse(self, response):
        # 将整个页面内容直接保存为 output.txt 文件
        with open('output.txt', 'w', encoding='utf-8') as file:
            file.write(response.text)

尝试直接将页面信息输出

使用Scarpy框架爬取链家网站经纪人列表_第4张图片

发现可以正常输出,说明网站解析没问题,没有触发反爬虫机制,问题可能出在定位上,但是更换了几种定位均无法爬取正确的信息,所以只能从output.txt文件下手

使用Scarpy框架爬取链家网站经纪人列表_第5张图片

经过观察发现,需要爬取的姓名信息在“name”与“agentUcid”之间,需要爬取的地址信息在“storeName”与“schoolTag”之间,于是可以使用正则表达式。

以下是从txt文件中提取信息的代码:

import re
import os

MAX_LENGTH = 1000  # 最大长度设定为1000个字符,可以根据实际情况调整

# 设置输入和输出文件的路径
input_file_path = '../../output.txt'  # 上一级目录中的 output.txt 文件
output_file_path = '../../extracted_content.txt'  # 上一级目录中的 extracted_content.txt 文件

# 读取文件内容
with open(input_file_path, 'r', encoding='utf-8') as file:
    data = file.read()

# 使用正则表达式匹配特定模式中的内容
pattern = re.compile(r'"name":"(.*?)","agentUcid":".*?","storeName":"(.*?)","schoolTag"', re.DOTALL)
matches = pattern.findall(data)

# 匹配到的内容写入到新的 txt 文件中
with open(output_file_path, 'w', encoding='utf-8') as output_file:
    for match in matches:
        name = match[0]
        store_name = match[1]

        # 如果 store_name 为空,则填入默认值 "无"
        if not store_name:
            store_name = "无"

        # 检查写入内容的长度,如果超出最大长度则不写入
        if len(f"{name}: {store_name}\n") <= MAX_LENGTH:
            output_file.write(f"{name}: {store_name}\n")

# 读取文件内容
with open(output_file_path, 'r', encoding='utf-8') as file:
    lines = file.readlines()

# 过滤重复的行
lines = list(set(lines))

# 将结果写回文件
with open(output_file_path, 'w', encoding='utf-8') as file:
    file.writelines(lines)
  1. 读取文件内容: 使用 open() 函数以只读模式打开指定路径的文件,并将文件内容读取到变量 data 中。
  2. 使用正则表达式匹配内容: 使用正则表达式模式 r'"name":"(.*?)","agentUcid":".*?","storeName":"(.*?)","schoolTag"' 来在 data 中寻找匹配的内容,并保存到 matches 变量中。
  3. 写入匹配到的内容到新的 txt 文件: 遍历匹配到的结果 matches,提取每个匹配项中的 namestore_name。然后,将这些信息写入到指定路径的新文件 extracted_content.txt 中。
  4. 过滤重复行: 读取新生成的文件内容到 lines 中,并将其转换为集合以消除重复行,最后重新将不重复的内容写回文件。

得到输出内容:

使用Scarpy框架爬取链家网站经纪人列表_第6张图片

最后一步,打开页面进行验证信息,随机搜索几个信息,发现能正常匹配上,不存在错位的问题,即为成功。


到这里整体就结束了,如果需要存入mongodb数据库,可参考上一篇文章,使用的方法类似,只需要注意一下数据库的连接,以及存入信息的格式。

四、整合代码

将下载页面信息与提取txt中信息的代码整合在一起的完整代码


import scrapy
import re

MAX_LENGTH = 500  # 最大长度设定为500个字符,可以根据实际情况调整
                  # 以防爬取到错误的信息


class LianjiaSpider(scrapy.Spider):
    name = 'lianjia'
    allowed_domains = ['m.lianjia.com']
    start_urls = ['https://m.lianjia.com/bj/jingjiren/?page_size=15&_t=1&offset=15']

    custom_settings = {
        'USER_AGENT': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1',
    }

    def parse(self, response):
        # 将整个页面内容直接保存为 output.txt 文件
        with open('output.txt', 'w', encoding='utf-8') as file:
            file.write(response.text)

        # 读取文件内容
        with open('output.txt', 'r', encoding='utf-8') as file:
            data = file.read()

        # 使用正则表达式匹配特定模式中的内容
        pattern = re.compile(r'"name":"(.*?)","agentUcid":".*?","storeName":"(.*?)","schoolTag"', re.DOTALL)
        matches = pattern.findall(data)

        # 匹配到的内容写入到新的 txt 文件中
        with open('extracted_content.txt', 'w', encoding='utf-8') as output_file:
            for match in matches:
                name = match[0]
                store_name = match[1]

                # 如果 store_name 为空,则填入默认值 "无"
                if not store_name:
                    store_name = "无"

                # 检查写入内容的长度,如果超出最大长度则不写入
                if len(f"{name}: {store_name}\n") <= MAX_LENGTH:
                    output_file.write(f"{name}: {store_name}\n")

        # 读取文件内容
        with open('extracted_content.txt', 'r', encoding='utf-8') as file:
            lines = file.readlines()

        # 过滤重复的行
        lines = list(set(lines))

        # 将结果写回文件
        with open('extracted_content.txt', 'w', encoding='utf-8') as file:
            file.writelines(lines)

最后在命令行中使用命令执行脚本

scrapy crawl lianjia

关于robots协议,经过尝试发现,在遵守robots协议的情况下也能正常爬取到信息,所有设置为True即可,不用做过多修改。


免责声明与版权声明

免责声明

本教程仅供教育和学习目的使用。作者力求提供准确和实用的信息,但不对信息的准确性、完整性和实时性作任何保证。读者在使用本教程中的任何信息、工具或代码时,须自行承担风险,并对其行为负全部责任。

作者对因使用本教程的信息、工具或代码所导致的任何直接或间接损失不承担责任。本教程中提供的代码示例仅供参考,读者应审慎检查代码并根据自身需求进行修改。

版权声明

本教程中的所有内容,包括但不限于文本、图像、代码示例,版权均归作者所有。未经作者许可,禁止未经授权转载、复制或修改本教程中的任何内容。

读者可将本教程用于个人学习和研究目的,但不得用于商业目的或未经授权的传播。任何未经许可的使用可能构成侵权行为,作者保留采取法律行动的权利。

附加信息

在任何情况下,本教程的信息均不构成任何形式的建议、担保或合同。作者保留随时更改或更新本教程内容的权利,无需提前通知。

你可能感兴趣的:(scrapy,python,beautifulsoup,pycharm)