网络爬虫学习(十三)

前一节(https://blog.youkuaiyun.com/weixin_44526949/article/details/86745455)我们通过分析一个电影网站,对该网站的前100的电影的相关信息进行了爬取。这种爬取是基于我们可以直接从网页源代码中看到要爬取的内容,只要写好正则表达式进行提取就可以了。但是,有时一些网站,我们并不能从网页源代码中直接找到我们需要的内容,这是因为,这些内容可能是通过Ajax加载,然后使用js进行渲染得到,这时就需要我们来分析网页请求。那么本期,我们通过分析Ajax来获取今日头条街拍美图。那么和之前一样,在进行爬取之前,首先需要进行目标站点的分析。我们打开要爬取的目标网站(https://www.toutiao.com/search/?keyword=%E8%A1%97%E6%8B%8D),然后和之前的步骤一样,需要分析网页源代码,通过分析网页源代码,来确定我们需要爬去的内容。整个流程框架分4步:

  1. 抓取索引页内容:利用requests请求目标站点,得到索引网页的HTML代码,返回结果。
  2. 抓取详情页内容:解析返回结果,得到详情页的链接,并进一步抓取详情页的信息。
  3. 下载图片与保存数据库:将图片下载到本地,并把页面信息及图片的url保存到MongoDB。
  4. 开启循环及多线程:对多页内容遍历,开启多线程提高抓取速度。

那么,接下来来完成这个项目,代码如下:

"""
本项目用来完成今日头条街拍美图
由于本次项目抓取的网页与之前的网页代码样式不同,本次的网页是通过ajax请求与js渲染而成的,无法直接
看到我们所要爬去的资源,此时我们需要分析get请求来对网页进行解析
"""
import requests
import re
import json
import pymongo
from bs4 import BeautifulSoup
from urllib.parse import urlencode
from requests.exceptions import RequestException
from config import *
import os
from hashlib import md5
from multiprocessing import Pool
client = pymongo.MongoClient(MONGO_URL, connect=False)
db = client[MONGO_DB]
def get_page_index(offset, keyword):
    data = {
        'offset': offset,
        'format': 'json',
        'keyword': 'keyword',
        'autoload': 'true',
        'count': '20',
        'cur_tab': 3
    }
    url = 'http://www.toutiao.com/search_content/?' + urlencode(data)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print('请求索引页出错')
        return None

def parse_page_index(html):
    data = json.loads(html)
    if data and 'data' in data.keys():
        for item in data.get('data'):
            yield item.get('article_url')

def get_page_detail(url):
    try:
        response = requests.get(url)
        if response.status_code == 200:
            return response.text
        return None
    except RequestException:
        print('请求详情页出错', url)
        return None

def parse_page_detail(html, url):
    soup = BeautifulSoup(html, 'lxml')
    title = soup.select('title')[0].get_text()
    print(title)
    images_pattern = re.compile('var gallery = (.*?);', re.S)
    result = re.search(images_pattern, html)
    if result:
        data = json.loads(result.group(1))
        if data and 'sub_images' in data.keys():
            sub_images = data.get('sub_images')
            images = [item.get('url') for item in sub_images]
            for image in images:
                download_image(image)
            return {
                'title': title,
                'url': url,
                'images': images
            }
def save_to_mongo(result):
    if db[MONGO_TABLE].insert(result):
        print('存储到MongoDB成功', result)
        return True
    return False

def download_image(url):
    print('正在下载', url)
    try:
        response = requests.get(url)
        if response.status_code == 200:
            save_image(response.content)
        return None
    except RequestException:
        print('请求图片出错', url)
        return None

def save_image(content):
    file_path = '{0}/{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg')
    if not os.path.exists(file_path):
        with open(file_path, 'wb') as f:
            f.write(content)
            f.close()
def main(offset):
    html = get_page_index(offset, KEYWORD)
    for url in parse_page_index(html):
        html = get_page_detail(url)
        if html:
            result = parse_page_detail(html, url)
            if result:
                save_to_mongo(result)


if __name__ == '__main__':
    groups = [x * 20 for x in range(GROUP_START, GROUP_END + 1)]
    pool = Pool()
    pool.map(main, groups)

我们需要将爬到的内容存储到MongoDB数据库中,需要另写一个模块,内容如下:

"""
将数据存储到MongoDB中
"""
MONGO_URL = 'localhost'
MONGO_DB = 'toutiao'
MONGO_TABLE = 'toutiao'




GROUP_START = 1
GROUP_END = 20


KEYWORD = '街拍'

以上的代码是一个通用的代码,适合任何一个用ajax加载和js渲染过得让我们无法直接看到所需要的网页内容的爬虫任务,只需要修改其中的参数即可,比如,当我们要爬取的任务是“体育”而不是“街拍”时,只需要更改原始代码中的URL和数据库配置中的相关参数,如KEYWORD='街拍'改为KEYWORD='想要的内容...'即可,只要是通过ajax加载和js渲染过的网页,我们从源代码中,无法直接找到我们所要爬取的内容,这时便可以通过分析get请求来对网页进行解析,进一步来获取我们需要的东西。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CSAIWQYB

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值