前言
最近也是在工作之余開發(fā)一個Android App,采用當前比較火的框架retrofit+rxjava+rxbus+lamda+greenDao+glide
等媳谁。有興趣的小伙伴可以關注一下我的github開源項目。本文主要介紹的是如何利用python
抓取糗百的熱門段子友酱。
開發(fā)環(huán)境
- Mac Os
- Python 2.7.10
- Node 7.8.0
編譯器:
- python-->Pycharm Ec
- node-->Visual Code Studio
以上開發(fā)環(huán)境以及編譯器大家可以自行百度 or google安裝晴音,本文就不一一介紹了。
爬蟲開發(fā)過程
準備
除了以上所說的編譯器以及開發(fā)環(huán)境的配置外握爷,我們還要明確設計爬蟲的目標墩邀,找到抓取的url以及分析目標url的dom結構黍翎。
- 目標:抓取糗百熱門段子第一頁中的,所有作者系羞,作者的頭像,以及對應的段子內(nèi)容
- url:http://www.qiushibaike.com/
- dom結構:
可以進入糗百首頁鸭叙,然后查看一下網(wǎng)頁源碼
{690D4AFF-447F-E481-B455-CDF6DAF63F7C}.png
如上圖中所示觉啊,可以看到每個完整的段子都是在class=article block untagged mb15
的div
下面。西面接著找一下對應作者的頭像以及姓名的節(jié)點![](//pic.qiushibaike.com/system/avtnew/2883/28831688/medium/2017051108472215.JPEG)
可以看到作者的名字是和img
的alt
一樣的因此只需要找到這個節(jié)點就可以得到姓名和頭像地址了沈贝。最后看下段子的內(nèi)容杠人,在class= content
的div
下面的span
中。至此所有要的信息的節(jié)點都找到了。
爬蟲書寫過程
框架分為五個個部分:爬蟲入口嗡善,url管理器辑莫,html下載器,html解析器罩引,html輸出器
爬蟲入口
新建spider_main.py
from baike import url_manager, html_download, html_parser, html_output
class SpiderMain(object):
def __init__(self):
self.urls = url_manager.UrlManager()
self.download = html_download.HtmlDown()
self.parser = html_parser.HtmlParser()
self.out = html_output.HtmlOutput()
def crow(self, root_url):
count = 1
self.urls.add_new_url(root_url)
while self.urls.has_new_url():
try:
new_url = self.urls.get_new_url()
print 'craw %d:%s' % (count, new_url)
html_count = self.download.download(new_url)
data = self.parser.parser(html_count)
self.out.collect_data(data)
if count == 1000:
break
count = count+1
except:
print 'craw failed:'
self.out.output_html()
if __name__ == '__main__':
root_url = 'http://www.qiushibaike.com/'
obj_spider = SpiderMain()
obj_spider.crow(root_url)
url管理器
class UrlManager(object):
def __init__(self):
self.new_urls = set()
self.older_urls = set()
def add_new_url(self, url):
if url is None:
return
if url not in self.new_urls and url not in self.older_urls:
self.new_urls.add(url)
def add_new_urls(self, urls):
if urls is None or len(urls) == 0:
return
for url in urls:
self.add_new_url(url)
def has_new_url(self):
return len(self.new_urls) != 0
def get_new_url(self):
url = self.new_urls.pop()
self.older_urls.add(url)
return url
html下載器
import requests
class HtmlDown(object):
def download(self, url):
if url is None:
return None
response = requests.get(url)
if response.status_code != 200:
return None
return response.text
html解析器
from bs4 import BeautifulSoup
class HtmlParser(object):
def __init__(self):
self.items = []
def parser(self, response):
if response is None:
return None
soup = BeautifulSoup(response, 'html.parser')
nodes = soup.findAll('div', class_='article block untagged mb15')
if nodes is None or len(nodes) == 0:
return None
for node in nodes:
image_node = node.img
image = 'http:' + image_node['src']
user_name = image_node['alt']
content_node = node.span.get_text()
data = {
'image_url': image,
'user_name': user_name,
'content': content_node
}
self.items.append(data)
return self.items
html輸出器
import json
class HtmlOutput(object):
def __init__(self):
self.data = []
def collect_data(self, data):
if data is None:
return
self.data = data
def output_html(self):
self.write_to_json(self.data)
fout = open('output.html', 'w')
fout.write("<html>")
fout.write("<body>")
fout.write("<table>")
fout.write("<tr>")
fout.write("<td>name</td>")
fout.write("<td>image</td>")
fout.write("<td>content</td>")
fout.write("</tr>")
if len(self.data) > 0:
for item in self.data:
fout.write("<tr>")
fout.write("<td>%s</td>" % (item['user_name']).encode('utf-8'))
fout.write("<td>%s</td>" % (item['image_url']))
fout.write("<td>%s</td>" % (item['content']).encode('utf-8'))
fout.write("</tr>")
fout.write("</table>")
fout.write("</body>")
fout.write("</html>")
fout.close()
def write_to_json(self, data):
if data is None:
return
f = open('json.txt', 'w')
json_str = json.dumps(data).encode('utf-8')
print json_str
f.write(json_str)
f.close()
最終將爬去的數(shù)據(jù)以html的形式和Json形式分表保存在當前路徑下面各吨。
只用node書寫簡單的接口
代碼如下:
ar http = require('http');
var rf = require("fs");
var data = rf.readFileSync("/Users/bear/Desktop/workplace/python/baike/json.txt", "utf-8");
console.log(data)
var jsonStr = {
'code': '1',
'message': '操作成功',
"data": {
'items': JSON.parse(data)
}
};
var json = JSON.stringify(jsonStr);
console.log(json);
http.createServer(function (req, res) {
res.writeHead(200);
res.end(json);
}).listen(1377, "0.0.0.0");
console.log('Server running at http://127.0.0.1:/');
然后本地瀏覽器打開:localhost:1377就能看到最終的json了
其它
app 端接口的調用可以看下Github上的開源項目