美文网首页
python 小爬虫入门

python 小爬虫入门

作者: Lupino | 来源:发表于2020-09-20 19:32 被阅读0次

大家晚上好
我叫李孟君,今晚由我来分享 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

爬虫

爬取 https://huabot.com

解析文章详情页

Screenshot 2020-09-20 at 6.19.16 PM.png
import 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 小爬虫入门

      本文链接:https://www.haomeiwen.com/subject/szkhjktx.html