36kr爬虫,前瞻
1 #!/usr/bin/env python 2 #-*- coding:utf-8 -*- 3 """ 4 @author:BanShaoHuan 5 @file: first.py 6 @time: 2018/05/07 7 @contact: banshaohuan@163.com 8 @site: 9 @software: PyCharm 10 11 # code is far away from bugs with the god animal protecting 12 I love animals. They taste delicious. 13 ┏┓ ┏┓ 14 ┏┛┻━━━┛┻┓ 15 ┃ ☃ ┃ 16 ┃ ┳┛ ┗┳ ┃ 17 ┃ ┻ ┃ 18 ┗━┓ ┏━┛ 19 ┃ ┗━━━┓ 20 ┃ 神兽保佑 ┣┓ 21 ┃ 永无BUG! ┏┛ 22 ┗┓┓┏━┳┓┏┛ 23 ┃┫┫ ┃┫┫ 24 ┗┻┛ ┗┻┛ 25 """ 26 27 import time 28 import json 29 import requests 30 import re 31 32 def get_html_encode(content_type, page_raw): 33 ''' 34 :param content_type:str, response header的参数 一般有编码方式 35 :param page_raw: str, html源码信息,里面的meta里面一般有编码方式 36 :return:返回编码方式 37 ''' 38 encode_list = re.findall( 39 r'charset=([0-9a-zA-Z_-]+)', content_type, re.I 40 ) 41 if encode_list: 42 return encode_list[0] 43 encode_list = re.findall( 44 r'<meta.+charset=[\'"]*([0-9a-zA-Z_-]+)', page_raw, re.I 45 ) 46 if encode_list: 47 return encode_list[0] 48 49 def _get_craw(url, headers, get_payload): 50 ''' 51 :param url:str,Request URL 52 :param headers: dict,Request Headers 53 :param get_payload: dict,Query String Parameters 54 :return: 55 ''' 56 r = requests.get(url, headers=headers, params=get_payload) 57 if r.status_code != 200: 58 raise Exception(r.status_code) 59 content_type = r.headers['Content-Type'] 60 if 'text/html' in content_type: 61 encoding = get_html_encode(content_type, r.text) 62 if encoding: 63 r.encoding = encoding 64 return r.text 65 elif 'application/json' in content_type: 66 return r.text 67 elif 'application/pdf' in content_type: 68 return r.content # 返回字节 69 elif 'image' in content_type:# 图片 70 return r.content # 返回字节 71 else: 72 return r.content 73 74 def _post_craw(url, headers, get_payload): 75 ''' 76 :param url:str,Request URL 77 :param headers: dict,Request Headers 78 :param get_payload: dict,Query String Parameters 79 :return: 80 ''' 81 r = requests.post(url, headers=headers, params=get_payload) 82 if r.status_code != 200: 83 raise Exception(r.status_code) 84 content_type = r.headers['Content-Type'] 85 if 'text/html' in content_type: 86 encoding = get_html_encode(content_type, r.text) 87 if encoding: 88 r.encoding = encoding 89 return r.text 90 elif 'application/json' in content_type: 91 return r.text 92 elif 'application/pdf' in content_type: 93 return r.content # 返回字节 94 elif 'image' in content_type:# 图片 95 return r.content # 返回字节 96 else: 97 return r.content 98 99 def _craw(method, url, headers=None, payload=None): 100 try: 101 if method == 'get': 102 return _get_craw(url, headers, payload) 103 elif method == 'post': 104 return _post_craw(url, headers, payload) 105 else: 106 raise Exception('method is wrong') 107 except Exception as e: 108 print(url) 109 print(e) 110 111 def _json(data): 112 # 解析json 113 data = json.loads(data) 114 articles = data['data']['items'] 115 print('文章id', '文章封面图片链接', '文章标题') 116 for article in articles: 117 print(article['id'], article['cover'], article['title']) 118 119 def _image(data): 120 # 抓取图片 121 data = json.loads(data) 122 articles = data['data']['items'] 123 for article in articles: 124 cover_url = article['cover'] 125 article_id = article['id'] 126 image_bytes = _craw('get', cover_url) 127 with open('img/{}.jpg'.format(article_id), 'wb') as f: 128 # 将字节写入文件,文件需要二进制形式 129 f.write(image_bytes) 130 131 if __name__ == '__main__': 132 url = 'http://36kr.com/api/search-column/mainsite' 133 get_payload = { 134 'per_page':20, 135 'page':1, 136 '_':str(int(time.time() * 1000)) 137 } 138 headers = { 139 'Host':'36kr.com', 140 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36' 141 } 142 data = _craw('get', url, headers, get_payload) 143 # _json(data) 144 # _image(data) 145 # 抓取详情页 146 data = json.loads(data) 147 articles = data['data']['items'] 148 for article in articles: 149 url = 'http://36kr.com/p/{}.html'.format(article['id']) 150 print(url) 151 html = _craw('get', url, headers) 152 print(html)
使用xpath进行爬虫前的小知识点,包括通过chrome对网页的抓包,判断网址的类型进行不同的操作
查看开发者工具network里面的信息,里面的信息比较多,因为html页面刚开始一般会加载js和css文件,我们不去管这些。我们抓取的是文本信息,所有我们一般查看type类型为docment和xhr的。docment类型一般的返回结果是html源码,xhr请求的返回结果一般是json格式。
鼠标往下滚动,触发翻页,有一个xhr请求,返回的结果,即是我们需要的文章列表页面的数据
可以看到有4部分:
(1)General一般包括请求的url,请求方法(get或者post),http请求服务器返回的状态码,200说明请求成功。
(2)Response Headers 是服务器返回的headers信息,一般会向浏览器设置cookie信息什么的,这里我们先不管。
(3)Request Headers 这一部分对于我们爬虫比较重要,是浏览器向服务器请求头信息,包括了浏览器当前状态的信息。一般我们要注意Cookie, Host, Referer, User-Agent等信息。
(4)Query String Parameters 请求参数,get方法请求即是url的问号后面那些东西,post方法是一些表单数据或者一些敏感信息,post方法参数在传输过程中会加密,所以post方法请求,保密性比较好。
到这里这个页面的抓包分析结束,Chrome抓包分析就是要找到我们所需要的数据是哪条请求链接,以及这个请求链接的Request Headers的参数和Query String Parameters参数。
从第一部分抓包分析可知:
(1)url为http://36kr.com/api/search-column/mainsite
(2)请求方法为get
(3)请求参数为per_page=20&page=2&_=1523873453996,从参数可知per_page=20是每页展示20篇文章,page=2为第2页,_=1523873453996即 _ 这个参数是请求当前时间点的时间戳
(4)headers当中的参数,一般比较重要的是:User-Agent, Referer, Host, Cookie等。如果遇到反爬,首先我们检查的就是headers,在可以获取到数据的情况下,headers里面的参数可以尽量少,获取不到的情况,就多添加一些,直到能够获取到数据。

浙公网安备 33010602011771号