python 爬蟲抓取今日頭條街拍圖片

1. 打開google瀏覽器,輸入www.toutiao.com, 搜索街拍。html

2.打開開發者選項,network監看加載的xhr, 數據是ajax異步加載的,能夠看到preview裏面的data數據python

3.下拉刷新查看加載的offset,每次加載20條數據,data是json數據,裏面的article_url,是圖集詳情頁的url。git

4.首先抓取索引頁的內容github

  data數據來自於索引頁的請求都裏面的query strajax

 1 # 提取索引頁的數據
 2 def get_page_index(offset, keyword):
 3     data = {
 4         'offset': offset,
 5         'format': 'json',
 6         'keyword': keyword,
 7         'autoload': 'true',
 8         'count': 20,
 9         'cur_tab': 1
10     }
11     # 向路由中出入參數, 構建完整url
12     url = 'http://www.toutiao.com/search_content/?' + urlencode(data)
13     try:
14         response = requests.get(url)
15         if response.status_code == 200:
16             return response.text
17         return None
18     except RequestException:
19         print('請求索引頁出錯')
20         return None

5. 接下來是解析索引頁的數據,提取出所須要的詳情頁的url,索引頁的data是json數據,裏面的article_url,是圖集詳情頁的url。mongodb

 1 # 解析索引頁的json數據(Preview),並提取詳情頁url
 2 def parse_page_index(html):
 3     try:
 4         data = json.loads(html)
 5         if data and 'data' in data.keys():
 6             for item in data.get('data'):
 7                 # 用生成器的方式,惰性獲取詳情頁的url
 8                 yield item.get('article_url')
 9     except JSONDecodeError:
10         pass

6. 有了詳情頁的url,接下來就是獲取詳情頁的數據和代碼了數據庫

 1 # 獲取詳情頁面的數據代碼
 2 def get_page_detail(url):
 3     try:
 4         response = requests.get(url, timeout=5)
 5         if response.status_code == 200:
 6             return response.text
 7         return None
 8     except RequestException:
 9         print('請求詳情頁出錯', url)
10         return None

7. 接着就是解析詳情頁面,並提取title, 和圖片url, 詳情頁代碼數據在Doc中查看, 注意提取的是組圖,非組圖被過濾了.url_list 是指三個地址都是圖片的地址,咱們只要有一個原始的url就能夠了。
  以某個詳情頁爲例,在瀏覽器中輸入http://www.toutiao.com/a6473742013958193678/。開發者選項,network, Docjson

 1 # 解析詳情頁面並提取title, 和圖片url
 2 def parse_page_detail(html, url):
 3     soup = BeautifulSoup(html, 'lxml')
 4     title = soup.select('title')[0].get_text()
 5     print(title)
 6     images_pattern = re.compile(r'gallery: (.*?),\n')
 7     result = re.search(images_pattern, html)
 8     if result:
 9         # 將json數據轉換爲python的字典對象
10         data = json.loads(result.group(1))
11         if data and 'sub_images' in data.keys():
12             sub_images = data.get('sub_images')
13             images = [item.get('url') for item in sub_images]
14             for image in images: download_image(image)
         # 返回標題,此詳情頁的url,和圖片url列表
15 return { 16 'title': title, 17 'url': url, 18 'images': images 19 }

8. 把解析提取的數據存儲到mongodb中,以字典的方式.瀏覽器

  先寫個mongo的配置文件config.py多線程

1 MONGO_URL = 'localhost'
2 MONGO_DB = 'toutiao'
3 MONGO_TABLE = 'toutiao'
4 
5 GROUP_START = 0
6 GROUP_END = 20
7 
8 KEYWORD = '街拍'

  而後鏈接本地mongo,存儲數據

1 client = pymongo.MongoClient(MONGO_URL, connect=False) # connect=False防止多線程在後臺屢次鏈接mongo數據庫
2 db = client[MONGO_DB]
3 
4 # 把詳情頁面的url和標題(title)以及組圖的地址list保存到mongo中
5 def save_to_mongo(result):
6     if db[MONGO_TABLE].insert(result):
7         print('存儲到MongoDB成功', result)
8         return True
9     return False

9. 下載圖片

 1 # 下載圖數據,並保存圖片
 2 def download_image(url):
 3     print('正在下載', url)
 4     try:
 5         response = requests.get(url)
 6         if response.status_code == 200:
 7             # response.content 爲二進制數據
 8             save_image(response.content)
 9         return None
10     except RequestException:
11         print('請求圖片失敗', url)
12         return None
13 
14 
15 # 保存圖片
16 def save_image(content):
17     # 使用md5生成加密名字,同時防止相同的圖片重複下載
18     file_path = '{0}/{1}.{2}'.format(os.getcwd(), md5(content).hexdigest(), 'jpg')
19     if not os.path.exists(file_path):
20         with open(file_path, 'wb') as f:
21             f.write(content)

10. 爬蟲主函數

1 def main(offset):
2     html = get_page_index(offset, KEYWORD)
3     for url in parse_page_index(html):
4         html = get_page_detail(url)
5         if html:
6             result = parse_page_detail(html, url)
7             if result: save_to_mongo(result)

11. 開啓多進程

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

12. 須要的庫函數

 1 import requests
 2 import re
 3 import pymongo
 4 from urllib.parse import urlencode
 5 from requests.exceptions import RequestException
 6 from json.decoder import JSONDecodeError
 7 from bs4 import BeautifulSoup
 8 import json
 9 import os
10 from hashlib import md5
11 from config import *
12 from multiprocessing import Pool

 

 完整代碼: https://github.com/huazhicai/Spider/tree/master/jiepai

相關文章
相關標籤/搜索