【Scrapy框架 正则+Pipeline+Middleware+MySql】爬取全站租房信息

【Scrapy框架 正则+Pipeline+Middleware+MySql】爬取全站租房信息,第1张

【Scrapy框架 正则+Pipeline+Middleware+MySql】爬取全站租房信息

今天的scrapy项目难度升级一下,不仅要用到pipeline导出数据到mysql,还要通过middleware实现随机User-Agent。

爬取目标网站为我爱我家

terminal 中startproject以及genspider这里不赘述,有问题可以评论在下面。

首先在item中声明爬取的item,这里我们抓取5个目标

  1. 标题
  2. 链接
  3. 位置
  4. 价格
  5. 大小
import scrapy


class WoaiwojiaItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    url = scrapy.Field()
    title = scrapy.Field()
    info = scrapy.Field()
    location = scrapy.Field()
    price = scrapy.Field()

之后,就要进入到spider文件中写代码了。不得不说,这个网站用xpath解析真的非常痛苦,还是pyquery来的方便又简单。不过因为scrapy只支持xpath css和re,所以头发掉光也没辙。

【注意】import在items文件中的item类

【关键】在for循环便利li节点中的xpath解析式,一定要记得有' . ' (括号中的点),不然就会回到顶层  进行遍历。在这里卡了很久。。 

解析完成,还要生成下一页的request,直接通过xpath找到下一页的相对url,并与base url拼接即可。这里注意dont filter = True,不然会被scrapy自动去重 

import scrapy
from woaiwojia.items import WoaiwojiaItem


class WiwjSpider(scrapy.Spider):
    name = 'wiwj'
    allowed_domains = ['https://bj.5i5j.com/zufang']
    start_urls = ['https://bj.5i5j.com/zufang/haidianqu/']
    base_url = 'https://bj.5i5j.com'

    def parse(self, response):
        lis = response.xpath('//ul[@]//li')
        #print(divs)
        #print(len(lis))
        item = WoaiwojiaItem()
        for li in lis:
            item['title'] = li.xpath('.//div[@]//h3//a/text()').extract_first()
            item['url'] = li.xpath('.//div[@]//a/@href').extract_first()
            #loc_pattern = re.compile('[sS](.*?)[sS]')
            #item['location'] = loc_pattern.search(str(li)
            #item['location'] = li.xpath('//div[@]//i[@/text()]').extract()
            #item['location'] = li.re_first('s+"(.*?)"')

            #正则提取出多个值,可以用用【index】定位
            # MySql插入值报错,因为没有在info和location后面加【index】,而mysql不能插入列表!
            item['info'] = li.re('

(.*?)

')[1].split('·')[1] item['location'] = li.re('s+(.*?)s+s+(.*?)s+<')[0] item['price'] = li.xpath('.//div[@]//p[@]//text()').extract_first() #item['info'] = li.xpath('//i[@/text()]').extract() yield item next = response.xpath('//div[@]//a').re('下一页')[0] next_url = self.base_url + next yield scrapy.Request(url=next_url,callback=self.parse,dont_filter=True)

到这里,可以尝试运行一下。

结果是什么呢?直接404报错。因为还有几个设置没有搞定 。

进入settings,添加ua以及关闭robots协议。

# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'User-Agent=Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False

再次运行。

可以返回第一页结果,然而到了第二页,又是404。为什么会这样呢?

因为生成下一页的request没有调用settings中的ua,所以自然就跪了。解决方法也简单,就要用到我们的middleware了。这个middleware在spider和downloader之间,传递request要经过它,返回response也经过它,所以在request被downloader处理前,给他添油加醋一下,就可以了。

【注意】middleware的process_request是必须有的,而且不能改名。

import random

class RandomUAMiddleware:
    def __init__(self):
        self.ua_list = [
            'User-Agent=Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
            'User-Agent=Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)',
            'User-Agent=Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)',
            'User-Agent=Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)',
            'User-Agent=Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)',
            'User-Agent=Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)',
            'User-Agent=Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)',
            'User-Agent=Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6',
            'User-Agent=Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1',
            'User-Agent=Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0',
        ]

    def process_request(self,request,spider):
        request.headers['User-Agent'] = random.choice(self.ua_list)

 之后,回到settings中,打开middleware

DOWNLOADER_MIDDLEWARES = {
    #'woaiwojia.middlewares.WoaiwojiaDownloaderMiddleware': 543,
    'woaiwojia.middlewares.RandomUAMiddleware': 543,
}

完成后,运行一下。完美!需要的数据都咔咔咔的出现了。可是,要对这些数据进行永久保存怎么整呢?这就要用到pipeline。它不仅可以进一步处理数据,还能保存数据到数据库。这里演示将数据导入mysql中。首先建立database以及table,这里不赘述,有问题可以评价下方。

在pipeline中,编辑如下代码。

【注意】一定要commit(),不然数据导不进去

from itemadapter import ItemAdapter
import pymysql

class WoaiwojiaPipeline:
    def __init__(self,host,port,user,pwd,db):
        self.host = host
        self.port = port
        self.user = user
        self.pwd = pwd
        self.db = db
        
    @classmethod
    def from_crawler(cls,crawler):
        return cls(
            host=crawler.settings.get('HOST'),
            port=crawler.settings.get('PORT'),
            user=crawler.settings.get('USER'),
            pwd=crawler.settings.get('PWD'),
            db=crawler.settings.get('DB'),
            )

    def open_spider(self,spider):
        self.conn = pymysql.connect(host=self.host,port=self.port,user=self.user,password=self.pwd,database=self.db)
        self.cursor = self.conn.cursor()

    def process_item(self, item, spider):
        title = item['title']
        url = item['url']
        info = item['info']
        location = item['location']
        price = item['price']
        sql = 'insert into wiwj(title,url,location,info,price) values(%s,%s,%s,%s,%s)'
        values = (title,url,location,info,price)
        self.cursor.execute(sql,values)
        self.conn.commit()

    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

在settings中设置mysql相关设置并打开pipeline

ITEM_PIPELINES = {
    'woaiwojia.pipelines.WoaiwojiaPipeline': 300,
}

HOST = 'localhost'
PORT = 3306
USER = 'root'
PWD = '123123123'
DB = 'wiwj'

ok 一切就绪。再次运行,数据就会全部导入数据库中啦。

成果展示

 肯定有人好奇,我这爬取的只有北京海淀区啊,哪里是全站。

这个就交给大家自行学习了,只需简单改动即可实现。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/zaji/5572434.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-12-14
下一篇2022-12-14

发表评论

登录后才能评论

评论列表(0条)

    保存