Scrapy 爬取今日头条街拍图片

scrapy 爬取今日头条图片保存至本地

之前用 requests 爬取过今日头条街拍的图片,当时只是爬取每篇文章的缩略图,今天尝试用 scrapy 来大规模爬取街拍详细图片。

分析页面
在这里插入图片描述
今日头条的内容是以 Ajax 加载而成的,我们爬取需要的是的 json 数据而非 html。
在这里插入图片描述
如上图所示,我们对爬取的 json 数据进行解析,即可得到文章标题,文章详细地址。

    def parse(self, response):
        text = response.text
        json_res = json.loads(text)

        if json_res.get('data'):
            for item in json_res.get('data'):
                # print(item)
                if item.get('cell_type') is not None:
                    continue
                title = item.get('title')
                if "toutiao" in item.get('article_url'):
                    it = ToutiaoJiapaiItem()
                    it['page_url'] = response.url
                    it['article_url'] = item.get('article_url')  # 详细网址
                    it['title'] = title  # 标题

                    yield Request(url=it['article_url'], headers=self.headers, callback=self.parse_page,
                                      meta={'item': it})

由于 json 数据中的图片列表,内容不全且都为缩略图,因此我们继续向下爬取。

分析详情页

在爬取过程中,发现详细页面大概有三种不同的页面展示。

**1. **
在这里插入图片描述
这种文章较为普遍,从上往下欣赏图片。当对该类型的页面进行爬取内容时,虽然返回的是 html 内容,但是排版完全乱了。
在这里插入图片描述
利用正则匹配或者BeautifulSoup提取都比较麻烦,在这里,我采用的是对字符串进行截取处理,提取出有效内容。

		text = response.text
        str_list = text.split('pgc-img')
        if str_list != None:
            for i in range(1, len(str_list)):
                if ""http:" in str_list[i]:
                    pic_url = str_list[i].split('"')[2]
                    pic_list.append(pic_url)

2.
在这里插入图片描述
这种是点击图片滑动欣赏图集,该页面返回的内容与上一种也不相同,因此需要另一种提取方式。
在这里插入图片描述
我们可以获取 JSON.parse 后的内容,将字符串转换为 json 进行提取。

# 利用正则提取图片地址
        pattern = re.compile('.*?gallery: JSON.parse\("(.*?)\"\)', re.S)
        result = re.search(pattern, text)
        if result:
            data = json.loads(result.group(1).replace('\\', ''))
            if data and 'sub_images' in data.keys():
                sub_images = data.get('sub_images')
                pic_list = [item.get('url') for item in sub_images]

3.
最后一种是街拍小视频,在这里并没有对视频进行处理。
在这里插入图片描述

最后,我们在 pipelines 文件里对获取到的 url 进行下载。

class ToutiaoJiepaiPipeline(ImagesPipeline):
    def get_media_requests(self, item, info):
        for image_url in item['photo_urls']:
            yield Request(image_url)

    def item_completed(self, results, item, info):
        image_paths = [x['path'] for ok,x in results if ok]
        if not image_paths:
            raise DropItem('图片未下载好')
        return item

效果如下。
在这里插入图片描述
详细代码如下:

import scrapy
import json
from scrapy_phantomjs.items import ToutiaoJiapaiItem
from urllib.parse import urlencode
from scrapy import Request
import re


class ToutiaoJiepaiSpider(scrapy.Spider):
    name = 'toutiao_jiepai'

    headers = {
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36'
    }

    def start_requests(self):
        # yield Request(url='https://www.toutiao.com/a6673629078630695427/', headers=self.headers,
        #               callback=self.parse_page)
        for i in range(0, 2):
            offset = i * 20
            params = {
                'aid': '24',
                'app_name': 'web_search',
                'offset': str(offset),
                'format': 'json',
                'keyword': '街拍',
                'autoload': 'true',
                'count': '20',
                'en_qc': '1',
                'cur_tab': '1',
                'from': 'search_tab',
                'pd': 'synthesis'
            }
            url = 'https://www.toutiao.com/api/search/content/?' + urlencode(params)

            yield Request(url=url, headers=self.headers, callback=self.parse)

    def parse(self, response):
        text = response.text
        json_res = json.loads(text)

        if json_res.get('data'):
            for item in json_res.get('data'):
                if item.get('cell_type') is not None:
                    continue
                title = item.get('title')
                if "toutiao" in item.get('article_url'):
                    it = ToutiaoJiapaiItem()
                    it['page_url'] = response.url
                    it['article_url'] = item.get('article_url')  # 详细网址
                    it['title'] = title  # 标题

                    yield Request(url=it['article_url'], headers=self.headers, callback=self.parse_page,
                                  meta={'item': it})

    def parse_page(self, response):
        item = response.meta['item']
        text = response.text

        pic_list = []

        str_list = text.split('pgc-img')
        if str_list != None:
            for i in range(1, len(str_list)):
                if ""http:" in str_list[i]:
                    pic_url = str_list[i].split('"')[2]
                    pic_list.append(pic_url)

        # 利用正则提取图片地址
        pattern = re.compile('.*?gallery: JSON.parse\("(.*?)\"\)', re.S)
        result = re.search(pattern, text)
        if result:
            data = json.loads(result.group(1).replace('\\', ''))
            if data and 'sub_images' in data.keys():
                sub_images = data.get('sub_images')
                pic_list = [item.get('url') for item in sub_images]
        item['photo_urls'] = pic_list

        yield item
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Scrapy 今日条可以分为以下步骤: 1. 创建 Scrapy 项目 ``` scrapy startproject toutiao ``` 2. 创建一个 Spider 在 Scrapy 项目中,每个虫都是由一个 Spider 类来定义的。在 `spiders` 文件夹下创建一个 `toutiao_spider.py` 文件,并编写以下代码: ```python import scrapy class ToutiaoSpider(scrapy.Spider): name = "toutiao" start_urls = [ 'https://www.toutiao.com/ch/news_hot/', ] def parse(self, response): for article in response.css('div.card'): yield { 'title': article.css('div.title-box a::text').get(), 'url': article.css('div.title-box a::attr(href)').get(), 'source': article.css('a.lbtn.source::text').get(), 'time': article.css('span.time::text').get(), } next_page = response.css('a.next::attr(href)').get() if next_page is not None: yield response.follow(next_page, self.parse) ``` 在 Spider 中,我们首先指定了 Spider 的名称和起始 URL,然后定义了一个 `parse` 方法,用于解析响应并提数据。在这个例子中,我们使用 CSS 选择器来提文章的标题、URL、来源和发布时间,并将其作为字典类型的 item 返回。最后,我们通过在响应中查找“下一页”的链接来实现翻页,并使用 `response.follow` 方法来跟踪这些链接,最终递归调用 `parse` 方法。 3. 运行 Spider 完成 Spider 的编写后,我们可以在命令行中运行以下命令来启动虫: ``` scrapy crawl toutiao -o articles.csv ``` 此命令将运行名为 `toutiao` 的 Spider,并将结果输出到 `articles.csv` 文件中。您可以将此文件用于进一步的数据分析和处理。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值