Python爬虫(二十)scrapy请求传参

281 阅读3分钟

上一篇中,我们应用scrapy框架的request请求爬取了贝壳网二手房模块的二手房列表的标题数据。

 

现在,我的需求变了,我现在不止想要每个房子的标题,我还想要没个房子的挂牌时间和上次交易时间。那我该怎么实现呢?

 

一般这种深度爬取的需求就需要用到scrapy框架的请求传参了。

 

何为请求传参呢?嗯……字面意思,请求的时候带参数。

 

这里,我还是将上一篇中的代码稍加改造来实现。

 

首先,我们先来梳理一下逻辑

1:爬取二手房列表页,每条数据的标题。

微信截图_20220624171123.png

 

2:再爬取一下详情页的URL,当然,贝壳网是在源码里边就能找到详情页的url,具体网站具体分析,如下图所示:

微信截图_20220624171418.png

 

3:目前需要深入爬取,那么我们就需要新定义一个方法来进入二手房详情页来爬取我们需要的数据。这里就需要用到我们的请求传参了。

语法:

yield scrapy.Request(url=detail_url, callback=self.parse_detail, meta={'item': item})

meta是一个字典(json)

detail_url是 详情页链接

 

下面展示一下,我这里测试使用的全部代码:

totalBeike.py

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2022/3/31 18:01
# @Author  : camellia
# @Email   : 805795955@qq.com
# @File    : beike.py
# @Software: PyCharm

import time

import scrapy
import asyncio
import requests
import random
from scrpayProject.items import ScrpayprojectItem

# 解析贝壳二手房页面的房源图片及标题
class TotalBeikeSpider(scrapy.Spider):
    name = 'totalBeike'
    # allowed_domains = ['www.beike.com']
    start_urls = ['https://dl.ke.com/ershoufang/']
    # start_urls = ['https://dl.ke.com/ershoufang/102105500760.html']

    page_num = 1

    def parse_detail(self,response):
        """
        爬取深一层的页面的数据
        """
        item = response.meta['item']
        start = response.xpath('//*[@id="introduction"]/div/div/div[2]/div[2]/ul/li[1]/text()').extract()
        buy = response.xpath('//*[@id="introduction"]/div/div/div[2]/div[2]/ul/li[3]/text()').extract()
        item['start'] = start[0]
        item['buy'] = buy[0]
        yield item  # 将item提交给管道

    def parse(self, response):
        divList = response.xpath('/html/body/div[1]/div[4]/div[1]/div[4]/ul/li[1]')
        title = []
        for div in divList:
            title = div.xpath('//ul[@class="sellListContent"]//img[@class="lj-lazy"]/@title').extract()
            hreflist = div.xpath('//ul[@class="sellListContent"]//div[@class="title"]//a[@data-click-event="SearchClick"]/@href').extract()
            for ind, it in enumerate(title):
                item = ScrpayprojectItem()
                item['author'] = it  # author属性必须在items.py中声明
                detail_url = hreflist[ind]
                # print(detail_url)
                # print(detail_url)
                # 爬取深一层的页面的数据
                yield scrapy.Request(url=detail_url, callback=self.parse_detail, meta={'item': item})
                yield item  # 将item提交给管道

            if self.page_num <= 1:
                new_url = 'https://dl.ke.com/ershoufang/pg'+str(self.page_num)+'/'
                self.page_num += 1
                # 手动请求发送:callback回调函数是专门用作与数据解析
                yield scrapy.Request(url=new_url,callback=self.parse)

 

Items.py

import scrapy


class ScrpayprojectItem(scrapy.Item):
    # define the fields for your item here like:
    author = scrapy.Field()
    start = scrapy.Field()
    buy = scrapy.Field()
    pass

 

pipelines.py

import pymysql

class mysqlPipeline:
    conn = None
    cursor = None
    # 重写父类的一个方法,该方法只在开始爬虫的时候调用一次
    def open_spider(self,spider):
        print('开始写入数据库……')
        self.conn = pymysql.Connect(host="39.107.142.167",port=3306,user='root',password='root@mule123',db='test')

    # 该方法每接到一个item就会调用一次
    def process_item(self, item, spider):
        self.cursor = self.conn.cursor()
        # print(item)
        sql = "insert into test (author,start,buy) values ('"+item["author"]+"','"+item["start"]+"','"+item["buy"]+"')"
        # print(sql)
        try:
            # print(sql)
            # 执行 插入语句
            self.cursor.execute(sql)
            # 数据库提交
            self.conn.commit()
        except Exception as e:
            # print("数据库回滚")
            # 数据库回滚
            self.conn.rollback()

        return item

    # 重写父类的一个方法,该方法只在结束爬虫的时候调用一次
    def close_spider(self,spider):
        print('结束写入数据库……')
        self.conn.close()
        self.cursor.close()

 

不清楚items.py以及pipelines.py文件在哪里,作何使用的同学,请移步《Python爬虫(十八)爬虫框架scrapy持久化存储

 

最后,轻点折腾,贝壳网是有反爬机制的……

 

有好的建议,请在下方输入你的评论。