• 分析AJAX抓取今日头条的街拍美图并把信息存入mongodb中


    今天学习分析ajax 请求,现把学得记录,

    把我们在今日头条搜索街拍美图的时候,今日头条会发起ajax请求去请求图片,所以我们在网页源码中不能找到图片的url,但是今日头条网页中有一个json 文件,这相文件中就包括单个图集的具体url,通过访问这个url ,又可以获取一个json 文件,这个json 文件中有个键是url_list  这个键的值是一个List ,这个list中就存入了具体单个图片的下载url ,通过request.get()方法去访问这个url ,然后把得到content以二进制的方式写入到本地,并把其他数据存入到mongodb中,

    代码如下,

      1 import requests
      2 import json
      3 from urllib.parse import urlencode
      4 from requests.exceptions import RequestException
      5 import re
      6 from bs4 import BeautifulSoup
      7 from config import *
      8 import pymongo
      9 from hashlib import md5
     10 import os
     11 from multiprocessing import Pool
     12 
     13 
     14 def get_page_index(offset, keyword):
     15     """传入要数据,获得详情页面"""
     16     data = {
     17         "autoload": "true",
     18         "count": 20,
     19         "cur_tab": 3,
     20         "format": "json",
     21         "from": "gallery",
     22         "keyword": keyword,
     23         "offset": offset,
     24     }
     25     url = "https://www.toutiao.com/search_content/?" + urlencode(data)
     26     try:
     27         response = requests.get(url)
     28         if response.status_code == 200:
     29             return response.text
     30         return None
     31     except RequestException:
     32         print("请求index页面失败")
     33         return None
     34 
     35 
     36 def parse_page_index(html):
     37     """头条街拍图片存在一个json中,json中的data就是单个图集的信息"""
     38     data = json.loads(html)
     39     if data and "data" in data.keys():
     40         for item in data.get("data"):
     41             yield item.get("article_url")
     42 
     43 
     44 def get_page_detail(url):
     45     """获得单个图集url的信息"""
     46     try:
     47         response = requests.get(url)
     48         if response.status_code == 200:
     49             return response.text
     50         return None
     51     except RequestException:
     52         print("请求详情页面失败")
     53         return None
     54 
     55 
     56 def parse_page_detail(html, url):
     57     """解析单位个图集url的网页信息,因为信息存放于一个json文件中,这个json文件嵌套在html中,所以使用re解析"""
     58     # 先用BeautifulSoup获得title.
     59     soup = BeautifulSoup(html, "lxml")
     60     title = soup.select("title")[0].get_text()
     61     print(title)
     62     images_pattern = re.compile('parse("(.*?)"),', re.S)
     63     result = re.search(images_pattern, html)
     64 
     65     if result:
     66         data = result.group(1)
     67         data = json.loads(data)
     68         if data and "url_list" in data.keys():
     69             url_list = data.get("url_list")
     70             images = [item.get("url") for item in url_list]
     71             for image in images:
     72                 # 调用函数下载图片到本地
     73                 download_imag(image)
     74             # 返回数据,返回的数据存入mongodb
     75             return {
     76                 "title": title,
     77                 "images": images,
     78                 "url": url,
     79             }
     80 
     81 
     82 def save_to_mongo(result):
     83     client = pymongo.MongoClient(MONGO_URL, connect=False)
     84     db = client[MONGO_DB]
     85     if db[MONGO_TABLE].insert(result):
     86         print("insert into mongo success", result)
     87         return True
     88     else:
     89         return False
     90 
     91 
     92 def download_imag(url):
     93     """# 下载图片到本地"""
     94     print("正在下载 :", url)
     95     try:
     96         response = requests.get(url)
     97         if response.status_code == 200:
     98             # response.content 返回二进制内容
     99             # response.text返回字符串
    100             save_image(response.content)
    101     except RequestException:
    102         print("请求图片失败", url)
    103 
    104 
    105 def save_image(content):
    106     """解析图片url的信息,把获得的信息写入本地文件中"""
    107     file_path = '{0}/{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), "jpg")
    108     if not os.path.exists(file_path):
    109         with open(file_path, "wb") as f:
    110             f.write(content)
    111 
    112 
    113 def main(offset):
    114     """主函数"""
    115     html = get_page_index(offset, KEYWORD)
    116     # 防止get_page_index没有取回数据
    117     if html is not None:
    118         for url in parse_page_index(html):
    119             html = get_page_detail(url)
    120             if html:
    121                 result = parse_page_detail(html, url)
    122                 save_to_mongo(result)
    123                 print(result)
    124     else:
    125         print("get_page_index 函数没有取到数据")
    126 
    127 
    128 if __name__ == "__main__":
    129     """使用多进程加快速度"""
    130     groups = [x * 20 for x in range(GROUP_START, GROUP_END)]
    131     pool = Pool()
    132     pool.map(main, groups)

    这个程度代码相对简单,逻辑清楚,程序之间参数传递及程序的跳转也不难,只是分析今日头条的ajax请求,及获得各个json文件相对复杂一点.

    我把程度的配置信息写在config.py 这个文件中,这样方法之后程序的重用,

    config.py 代码如下:

    MONGO_URL="localhost"
    MONGO_DB="toutiao"
    MONGO_TABLE="toutiao"
    
    GROUP_START = 1 # 定义起始循环点
    GROUP_END = 20 # 定义终止循环点
    KEYWORD="街拍"

    通过这个程序,学会了分析,这种通过发起ajax请求而获取数据的网页的源码分析.这个程序不足的地方是,这个程序是用requsts库做的解析,程序会是用函数而不是类去实现,后续要把这个程序改用scrapy 库去实现.

  • 相关阅读:
    ssh环境的搭建,基于注解和配置文件使用
    myeclipse db browser 新建数据源
    区别jquery对象和dom对象及转换方法
    C++中map容器的说明和使用技巧
    csh shell 语法 例子
    如何选择显示器
    Vim简明教程【CoolShell】
    perl
    perlretut
    ssh 配置详解
  • 原文地址:https://www.cnblogs.com/liuqianli/p/8337465.html
Copyright © 2020-2023  润新知