使用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为爬虫文件名

得到以下文件目录即可

二、观察待爬取页面

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

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

尝试使用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)

尝试直接将页面信息输出

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

经过观察发现,需要爬取的姓名信息在“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 中,并将其转换为集合以消除重复行,最后重新将不重复的内容写回文件。

得到输出内容:

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


到这里整体就结束了,如果需要存入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即可,不用做过多修改。

五、新增存入mongodb数据库

lianjia.py文件

import scrapy
import re
import pymongo

MAX_LENGTH = 1000

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):
        # 使用正则表达式匹配特定模式中的内容
        pattern = re.compile(r'"name":"(.*?)","agentUcid":".*?","storeName":"(.*?)","schoolTag"', re.DOTALL)
        matches = pattern.findall(response.text)

        # 创建 MongoDB 连接
        client = pymongo.MongoClient('mongodb://localhost:27017/')  # 更改为你的 MongoDB 连接地址
        db = client['lianjia']  # 更改为你想要使用的数据库名称
        collection = db['lianjia']  # 更改为你想要保存信息的集合名称

        # 将匹配到的内容写入 MongoDB
        for match in matches:
            name = match[0]
            store_name = match[1] if match[1] else "无"

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

        client.close()  # 关闭 MongoDB 连接

items.py

import scrapy

class AgentItem(scrapy.Item):
    name = scrapy.Field()
    store_name = scrapy.Field()

settings.py

在文件末尾添加以下内容

MONGODB_URI = 'mongodb://localhost:27017/'
MONGODB_DATABASE = 'lianjia'  # 更改为你想要使用的数据库名称

pipelines.py

import pymongo
from .items import AgentItem

class MongoDBPipeline(object):
    collection_name = 'agents'

    def __init__(self, mongo_uri, mongo_db):
        self.mongo_uri = mongo_uri
        self.mongo_db = mongo_db

    @classmethod
    def from_crawler(cls, crawler):
        return cls(
            mongo_uri=crawler.settings.get('MONGODB_URI'),
            mongo_db=crawler.settings.get('MONGODB_DATABASE', 'items')
        )

    def open_spider(self, spider):
        self.client = pymongo.MongoClient(self.mongo_uri)
        self.db = self.client[self.mongo_db]

    def close_spider(self, spider):
        self.client.close()

    def process_item(self, item, spider):
        if isinstance(item, AgentItem):
            self.db[self.collection_name].insert_one(dict(item))
        return item

mongodb数据库截图


免责声明与版权声明

免责声明

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

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

版权声明

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

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

附加信息

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

  • 23
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值