python 小爬虫入门
大家晚上好
我叫李孟君,今晚由我来分享 python 小爬虫入门。
自学介绍
大学的时候我学的是 动物科学,与计算机没有多大的关系。
在一次机缘巧合下,我接触了 python,当时不喜欢看厚厚的书,
我在网上找到了一本不到 100 页的书,名字叫 a byte of python,
这本书纯英文版的,我选了前面不到 20 页的几个章,开始了自学。
曾听人说过,自己学习编程语言会很不系统,但事实上不是这样子的。
虽然自学学到的内容和培训机构出来的有很大的不同,但基础功底会更加深厚。就以我自己为例子吧,我学python的时候学更多的是哪些基本的内容,那些花里胡哨的库呀代码呀我了解并不多。而我自学所用的那本书 a byte of python,它刚刚好把 python 基本的介绍得非常透彻。虽然它是一本纯英文的书,但这并不影响我学习 python。
把基础打扎实了再去学习其他内容,反而事半功倍。
爬虫简介
爬虫到底是啥东西呢?当我跟朋友提起的时候,他觉得这个好神奇啊,
其实它只不过是把我们本来要通过手动做的事情自动化掉就这样子。
比如我打开一个网页浏览后继续打开下一个网页,就这么一个操作而已,然后现在我用python 把它实现出来。那么我没写一个爬虫需要具备什么知识吗?
其实主要具备的知识并不多,只要了解一些python的基本语法,操作方法,然后再结合网页上面的一些内容,配合一下 Google 浏览器那个审查元素的工具。
我们打开网页的时候是通过手 用鼠标点击一个页面这样子,那在python上面打开一个网页是通过一个叫 requests 的库去解决。
我们用 Google 浏览器审查元素去看 html 的结构,我们看到的那些内容其实是已经被渲染出来,我们要抓这些内容很简单就是通过鼠标复制粘贴一下就可以了。在 python 里面我们用到一个叫 beautifulsoup4 这样子的一个库,我们用它来解析我们的网页,把我们所要的内容解析出来,这是一部分吗。然后接下来我们要获取下一页面,我们的目标是要把网站上的所有页面都获取出来,然后我们就寻着找到下一个页面的地址。
找到下一个页地址后,这边做好是把地址和网页的原地址 join
一下,拼接起来,我们会用到一个叫做 urllib 的库,就可以把链接地址变成一个绝对地址,这样子的话,然后我们把链接地址放到一个队列里面,
然后每次从队列里面 pop 出一个,抓完后再把地址放回去,这样子就完成了。这么个小爬虫就这样子做出来了。下面我来具体介绍,这个是怎么实现的,我会写一些例子出来展示给大家看。
五分钟入门 python
安装
来个 hello world!
print('Hello world!')
基本语法
布尔类型
True
False
数字类型
1,2,3
1.1,1.2
数字运算
+
-
*
/
文本类型
"a"
'a'
'''b'''
"""b"""
文本格式化
'{}'.format('hello')
'%s'$('hello')
列表
[1,2,3,5]
['a', 'b', 'c', 'd']
字典
{
'key': 'value'
}
逻辑判断
if a == b:
pass
elif b == c:
pass
else:
pass
循环
for 循环
for i in range(10):
print(i)
for i in [1,2,3,4]:
print(i)
while 循环
while True:
pass
函数
函数定义
def func1():
pass
def func2(arg1, arg2):
pass
def func3(arg1, arg2=None):
pass
函数调用
func1()
func2(arg1, arg2)
func3(arg1)
软件包及其安装方法
pip install requests beautifulsoup4
import requests
from bs4 import BeautifulSoup
爬虫
解析文章详情页
Screenshot 2020-09-20 at 6.19.16 PM.pngimport requests
from bs4 import BeautifulSoup
import re
# 解析我们要抓页面的内容
rsp = requests.get('https://huabot.com/t/46899.html')
soup = BeautifulSoup(rsp.text, features="html.parser")
# 通过审查元素,我们发现内容在 div class card 面
cards = soup.find_all('div', {'class': 'card'})
# 通过简要分析我们注意到包含内容的 card 有 data-title 这个属性
got_card = None
for card in cards:
if card.get('data-title'):
got_card = card
title = got_card.get('data-title').strip()
summary = got_card.get('data-summary').strip()
print(title)
print(summary)
# 正文内容在 card-content 里面
card_content = got_card.find('div', {'class': 'card-content'})
print(card_content)
# 清空 card-title
card_title = card_content.find('span', {'class': 'card-title'})
card_title.extract()
print(card_content)
# 清空分享按钮
bd_share = card_content.find('div', {'class': 'bdsharebuttonbox'})
bd_share.extract()
print(card_content)
# 清空图片属性
imgs = card_content.find_all('img')
for img in imgs:
if not img.get('src'):
img.extract()
img.attrs.pop('alt', None)
img.attrs.pop('title', None)
print(card_content)
# 渲染出内容
content = str(card_content.renderContents(), 'utf8')
# 清空无用的img 标签
content = content.replace('</img>', '')
content = re.sub('[\n\r]+', '\n', content)
if content.startswith('<br/>'):
content = content[5:]
print(content)
解析链接地址
import requests
from bs4 import BeautifulSoup
import re
# 解析我们要抓详情页面的地址
base_url = 'https://huabot.com'
rsp = requests.get('https://huabot.com/p/1')
soup = BeautifulSoup(rsp.text, features="html.parser")
# 通过审查元素,我们发现内容在 div class card 面
cards = soup.find_all('div', {'class': 'card'})
# 通过简要分析我们注意到包含内容的 card 有 data-title 这个属性
links = []
for card in cards:
card_title = card.find('span', {'class': 'card-title'})
if card_title:
card_link = card_title.find('a')
link = card_link.get('href')
links.append(base_url + link)
print(links)
整合成完整爬虫
import requests
from bs4 import BeautifulSoup
import re
import json
base_url = 'https://huabot.com'
def crawl_entry(url):
# 解析我们要抓页面的内容
print('crawl_entry:', url)
rsp = requests.get(url)
soup = BeautifulSoup(rsp.text, features="html.parser")
links = find_links(soup)
# 通过审查元素,我们发现内容在 div class card 面
cards = soup.find_all('div', {'class': 'card'})
# 通过简要分析我们注意到包含内容的 card 有 data-title 这个属性
got_card = None
for card in cards:
if card.get('data-title'):
got_card = card
title = got_card.get('data-title').strip()
summary = got_card.get('data-summary').strip()
# 正文内容在 card-content 里面
card_content = got_card.find('div', {'class': 'card-content'})
# 清空 card-title
card_title = card_content.find('span', {'class': 'card-title'})
card_title.extract()
# 清空分享按钮
bd_share = card_content.find('div', {'class': 'bdsharebuttonbox'})
bd_share.extract()
# 清空图片属性
imgs = card_content.find_all('img')
for img in imgs:
if not img.get('src'):
img.extract()
img.attrs.pop('alt', None)
img.attrs.pop('title', None)
# 渲染出内容
content = str(card_content.renderContents(), 'utf8')
# 清空无用的img 标签
content = content.replace('</img>', '')
content = re.sub('[\n\r]+', '\n', content)
if content.startswith('<br/>'):
content = content[5:]
content = content.strip()
return {
'title': title,
'summary': summary,
'content': content,
'url': url
}, links
def crawl_links(page):
print('crawl_links:', page)
rsp = requests.get('https://huabot.com/p/{}'.format(page))
soup = BeautifulSoup(rsp.text, features="html.parser")
return find_links(soup)
def find_links(soup):
# 通过审查元素,我们发现内容在 div class card 面
cards = soup.find_all('div', {'class': 'card'})
links = []
for card in cards:
card_title = card.find('span', {'class': 'card-title'})
if card_title:
card_link = card_title.find('a')
link = card_link.get('href')
links.append(base_url + link)
return links
def main():
followed = []
links = []
for page in range(1,10):
new_links = crawl_links(page)
for link in new_links:
if link in followed:
continue
if link in links:
continue
links.append(link)
while True:
if len(links) == 0:
break
link = links.pop()
entry, new_links = crawl_entry(link)
followed.append(link)
with open('entities.json', 'a') as f:
f.write(json.dumps(entry))
for link in new_links:
if link in followed:
continue
if link in links:
continue
links.append(link)
main()
小结
- 自学可能基础更扎实
- 基础打扎实了再去学习其他内容,反而事半功倍
- 爬虫只不过是把我们本来要通过手动做的事情自动化掉而已
- 写爬虫只需要了解python基础知识,和 requests,beautifulsoup4 几个库就够
- https://github.com/Lupino/mini-spider
- https://github.com/Lupino/hack-editor