在网络数据抓取和处理中,Scrapy是一个强大的工具,它能够简化爬虫的构建过程。本文将介绍如何使用Scrapy抓取链家网站的经纪人信息,并通过Python对这些信息进行处理。
确保您的计算机上安装了 Python。您可以在Python官方网站上下载并安装最新版本的 Python。
在安装 Python 时,通常会一并安装 pip,它是 Python 包管理工具。但如果您的 Python 版本较旧或者没有安装 pip,请根据您的操作系统安装 pip。
使用 pip 安装 Scrapy。在命令行中执行以下命令:
pip install scrapy
这将安装最新版本的 Scrapy 爬虫框架。
要将爬取到的数据存储到 MongoDB 中,需要安装 pymongo 这个 Python MongoDB 客户端库。在命令行中执行以下命令:
pip install pymongo
如果您尚未安装 MongoDB 数据库,您可以从MongoDB官方网站下载适用于您操作系统的版本并进行安装。
确保您已经在本地启动了 MongoDB 服务。然后使用以下命令连接到 MongoDB,并创建一个数据库和集合来存储爬取到的数据:
mongo
use pachong # 创建名为 pachong 的数据库
db.createCollection("pachong") # 在 pachong 数据库中创建名为 pachong 的集合
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)
open()
函数以只读模式打开指定路径的文件,并将文件内容读取到变量 data
中。r'"name":"(.*?)","agentUcid":".*?","storeName":"(.*?)","schoolTag"'
来在 data
中寻找匹配的内容,并保存到 matches
变量中。matches
,提取每个匹配项中的 name
和 store_name
。然后,将这些信息写入到指定路径的新文件 extracted_content.txt
中。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即可,不用做过多修改。
本教程仅供教育和学习目的使用。作者力求提供准确和实用的信息,但不对信息的准确性、完整性和实时性作任何保证。读者在使用本教程中的任何信息、工具或代码时,须自行承担风险,并对其行为负全部责任。
作者对因使用本教程的信息、工具或代码所导致的任何直接或间接损失不承担责任。本教程中提供的代码示例仅供参考,读者应审慎检查代码并根据自身需求进行修改。
本教程中的所有内容,包括但不限于文本、图像、代码示例,版权均归作者所有。未经作者许可,禁止未经授权转载、复制或修改本教程中的任何内容。
读者可将本教程用于个人学习和研究目的,但不得用于商业目的或未经授权的传播。任何未经许可的使用可能构成侵权行为,作者保留采取法律行动的权利。
在任何情况下,本教程的信息均不构成任何形式的建议、担保或合同。作者保留随时更改或更新本教程内容的权利,无需提前通知。