scrapy爬虫爬取动态网站

爬取360图片上的美女图片

360图片网站上的图片是动态加载的,动态加载 就是通过ajax请求接口拿到数据喧染在网页上。我们就可以通过游览器的开发者工具分析,在我们向下拉动窗口时就会出现这么个请求,如图所示:
这里写图片描述

所以就判定这个url就是ajax请求的接口:,http://image.so.com/zj?ch=beauty&sn=30&listtype=new&temp=1,通过分析,sn=30 表示取的是前面30条数据,sn=60取的是30到60条的数据,我们就可以通过改变sn的数来拿到不同的数据,下面就开始我们的scrap项目:

# 在虚拟环境里创建项目
scrapy startproject  image360
# 创建蜘蛛
scrapy  genspider image  image.so.com

项目目录结构如下:
这里写图片描述

首先建立保存数据的模型:在items.py文件中

import scrapy


class ImageItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field() # 图片的标题
    tag = scrapy.Field() # 图片的标签
    width = scrapy.Field() # 图片的宽度
    height = scrapy.Field() # 图片的高度
    url = scrapy.Field() # 图片的url

开始写蜘蛛:在iamge.py文件中

import scrapy
from urllib.parse import urlencode
from json import loads

class ImageSpider(scrapy.Spider):
    name = 'image' # 蜘蛛的名字
    allowed_domains = ['image.so.com'] # 允许访问的域名

    # 因为不和以前一样给一个初始url,所以需要重写父类的start_requests方法
    def strat_requests(self):
        # 定义一个基础的url
        base_url = 'http://image.so.com/zj?'
        # 把固定的参数保存在一个字典里
        param = {'ch': 'beauty', 'listtype': 'new', 'temp': 1}
        # 我们拿数据只需要改变sn的值,所以我们来个循环,我们拿300条数据
        for page in range(10):
            # 把sn和对应的数添加到字典里
            param['sn'] = page * 30
            # 一个完整的url   
            full_url = base_url + urlencode(param)
            # 返回一个生成器,
             yield scrapy.Request(url=full_url, callback=self.parse)

    def     def parse(self, response):
        # 把从接口里拿到的数据转成字典
        model_dict = loads(response.text)
        # 找到对应的数据放在item里
        for elem in model_dict['list']:
            item = ImageItem()
            item['title'] = elem['group_title']
            item['tag'] = elem['tag']
            item['width'] = elem['cover_width']
            item['height'] = elem['cover_height']
            item['url'] = elem['qhimg_url']
            yield item

数据的持久化:在pipelines.py文件中

from scrapy import Request
from scrapy.exceptions import DropItem
from scrapy.pipelines.images import ImagesPipeline
from pymongo import MongoClient


# 下载图片的类,继承了scrap的ImagesPipeline类,并且重写了里面3个方法
class SaveImagePipeline(ImagesPipeline):

    def get_media_requests(self, item, info):
        yield Request(url=item['url'])

    def item_completed(self, results, item, info):
        if not results[0][0]:
            raise DropItem('下载失败')
        return item

    # 获取文件的文件名的方法
    def file_path(self, request, response=None, info=None):
        return request.url.split('/')[-1]


# 保存到数据库的类
class SaveToMongoPipeline(object):

    def __init__(self, mongo_url, db_name):
        self.mongo_url = mongo_url
        self.db_name = db_name
        self.client = None
        self.db = None
        self.collect = None

    # 把item数据存入mongo数据库里
    def process_item(self, item, spider):
        # item['image_name'] = item['url'].split('/')[-1]
        # self.db.image.insert(dict(item))

        self.collect.insert_one(dict(item))
        return item

    # 创建连接mongo数据库的方法,在开始爬虫程序时自动调用
    def open_spider(self, spider):
        self.client = MongoClient(self.mongo_url)
        self.db = self.client[self.db_name]
        self.collect = self.db.image

    # 关闭连接的方法,在爬虫程序结束时自动调用
    def close_spider(self, spider):
        self.client.close()

    # 这是个类方法
    @classmethod
    def from_crawler(cls, crawler):
        # 当return cls时就会调用该类的初始方法__init__,就把连接mango数据库的参数和数据库名字传过去
        # crawler.setting.get('MONGO_URL')就是拿到settings.py文件里设置的 MONGO_URL
        return cls(crawler.settings.get('MONGO_URL'),
                   crawler.settings.get('MONGO_DB'))

在配置文件中开启pipelines

这里写图片描述

使用webdriver

from selenium import webdriver
from bs4 import BeautifulSoup
import requests

def main():
    driver = webdriver.Chrome()
    driver.get('https://v.taobao.com/v/content/live?catetype=704&from=taonvlang')
    soup = BeautifulSoup(driver.page_source, 'lxml')
    for img_tag in soup.body.select('img[src]'):
        url = img_tag.attrs['src']
        try:
            if not str(url).startswith('http'):
                url = 'http:' + url
                filename = url[url.rfind('/') + 1:]
                resp = requests.get(url)
                with open('../images/' + filename,'wb') as f:
                    f.write(resp.content)
        except OSError:
            print(filename + '下载失败')
    print('图片下载完成')


if __name__ == '__main__':
    main()
### 使用 Scrapy 爬虫框架爬取豆瓣数据的步骤 Scrapy 是一个功能强大且广泛使用的开源爬虫框架,能够帮助快速构建爬虫项目并高效地从网站中提取数据[^1]。以下是使用 Scrapy 爬取豆瓣数据的具体方法: #### 1. 创建 Scrapy 项目 首先需要创建一个新的 Scrapy 项目。通过命令行运行以下命令: ```bash scrapy startproject douban_spider ``` 这将生成一个名为 `douban_spider` 的项目目录结构。 #### 2. 定义目标数据模型 在 Scrapy 中,`items.py` 文件用于定义爬取的数据模型。假设我们要爬取豆瓣电影 Top 250 的信息,包括电影名称、评分和简介等字段。可以在 `items.py` 中定义如下内容: ```python import scrapy class MovieItem(scrapy.Item): title = scrapy.Field() # 电影名称 score = scrapy.Field() # 评分 description = scrapy.Field() # 简介 ``` #### 3. 编写爬虫逻辑 接下来,在 `spiders` 目录下创建一个新的爬虫文件,例如 `douban_movie.py`,并在其中实现具体的爬取逻辑。以下是一个简单的示例代码: ```python import scrapy from douban_spider.items import MovieItem class DoubanMovieSpider(scrapy.Spider): name = "douban_movie" # 爬虫名称 allowed_domains = ["movie.douban.com"] # 允许爬取的域名 start_urls = ["https://movie.douban.com/top250"] # 起始 URL def parse(self, response): for movie in response.css("div.item"): # 遍历每部电影 item = MovieItem() item["title"] = movie.css("span.title::text").get() # 提取电影名称 item["score"] = movie.css("span.rating_num::text").get() # 提取评分 item["description"] = movie.css("span.inq::text").get() # 提取简介 yield item # 返回数据项 next_page = response.css("span.next a::attr(href)").get() # 获取下一页链接 if next_page is not None: yield response.follow(next_page, self.parse) # 继续爬取下一页 ``` #### 4. 启动爬虫 完成上述设置后,可以通过以下命令启动爬虫: ```bash scrapy crawl douban_movie ``` 这里的 `douban_movie` 是我们在爬虫类中定义的 `name` 属性值[^2]。如果需要同时启动多个爬虫任务,可以打开多个终端,并确保进入项目的二级目录后再执行命令。 #### 5. 数据存储 默认情况下,Scrapy 会将爬取到的数据输出到控制台。如果需要保存为文件,可以在命令中添加参数。例如,将结果保存为 JSON 文件: ```bash scrapy crawl douban_movie -o movies.json ``` 此外,还可以通过配置 `pipelines.py` 文件将数据保存到数据库中。例如,使用 MongoDB 存储数据时,可以在 `pipelines.py` 中实现如下代码: ```python import pymongo class MongoDBPipeline: def open_spider(self, spider): self.client = pymongo.MongoClient("mongodb://localhost:27017/") self.db = self.client["douban"] self.collection = self.db["movies"] def process_item(self, item, spider): self.collection.insert_one(dict(item)) return item def close_spider(self, spider): self.client.close() ``` 然后在 `settings.py` 文件中启用该管道: ```python ITEM_PIPELINES = { 'douban_spider.pipelines.MongoDBPipeline': 300, } ``` ### 注意事项 - 在爬取豆瓣数据时,需要注意遵守其robots协议[^3]。 - 如果遇到反爬机制(如验证码或 IP 封禁),可以考虑使用代理或设置合理的下载延迟。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值