热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python爬虫入门到入职02:编写第一个爬虫程序

教程中的项目请跟着在pycharm中写一遍,注意查看注释内容。推荐的课外练习请自行完成,完成后再查看参考代码。本章知识点:python基础使用requests库发送请求使用beau

教程中的项目请跟着在pycharm中写一遍,注意查看注释内容。推荐的课外练习请自行完成,完成后再查看参考代码。

本章知识点:

  • python基础
  • 使用requests库发送请求
  • 使用beautifulsoup解析网页源码

python基础学习

本教程爬虫开发需要python语言基础,请根据自身情况选择:

  • 我是零基础:请先学习python基础教程,强烈推荐:廖雪峰的python教程。
    • 重点学习章节:python基础函数高级特性模块面相对象编程错误、调试和测试IO编程
    • 初步了解章节:进程和线程正则表达式常用内建模块常用第三方模块virtualenv网络编程Web开发。这些内容十分重要,但初期涉及不多。
    • 暂时跳过章节:面向对象高级编程函数式编程图形界面电子邮件访问数据库异步IO实战,这些内容会在Python爬虫-高级进阶系列教程涉及。
    • 学习时间:2~3天
  • 我有编程基础:直接开始爬虫教程。

第一个爬虫程序:游戏葡萄

创建一个game_grape.py文件,写入代码:

from urllib import request # 导入urllib中的request模块
response= request.urlopen('http://youxiputao.com/') # 用urlopen()函数执行一次请求,地址是游戏葡萄的首页,并把返回对象赋值给response变量。
html = response.read().decode() # 从response中读取结果,解码成str类型的字符串,就是我们的html源码。
print(html) # 在控制台打印html源码。

执行程序,控制台打印出首页的html源码:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

程序运行成功,超级简单有木有!

其实爬虫的本质就是:
发起请求
获得响应
解析结果。企业中千万级爬虫、分布式爬虫都是在这个基础上抓取得更快、存储得更多、突破各种反爬虫措施而已。

使用requests进行抓取

使用python内置的urllib包虽然可以进行抓取,但使用非常不方便,特别是面对复杂的网络请求时,使用起来会力不从心。我们来尝试用第三方网络请求工具requests重写爬虫。

import requests
response = requests.get('http://youxiputao.com/')
print(response.text)

执行程序,报错:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

requests是第三方库,需要安装后使用:按住Win+R,输入powershell(Win10以下输入cmd),按回车键,输入命令pip install requests,如图:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

第一次安装需要下载,如果速度太慢安装失败,可以把下载源更换为清华大学镜像:输入pip -V命令,查看pip版本:

  • 高于10.0版本,执行命令:pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
  • 低于10.0版本,参考教程:设置pip安装源为国内清华大学镜像

换源之后重新安装requests,出现Successfully installed xxx即为安装成功。

再次执行代码,成功打印出html源码:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

源码解析

我们想解析网页源码,获得新闻标题和链接,使用第三方库BeautifulSoup解析工具:pip install bs4。打开Chrome浏览器,右键点击新闻标题,点击检查,查看新闻标题的位置:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

根据源码位置找到标题,如图:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

修改代码:

import requests
from bs4 import BeautifulSoup
response = requests.get('http://youxiputao.com/') # 发起网络请求,获得响应
soup = BeautifulSoup(response.text, 'html.parser') # 使用BeautifulSoup解析,查找我们想要的内容。html.parser是系统内置的解析方案,可以不填但是会报警告(warning)
ul_node = soup.find('ul', {'class': 'news-list'}) # 查找class值为news-list的ul标签,
li_node = ul_node.find('li') # 在ul标签下查找第一个li标签
h4_node = li_node.find('h4') # 在li标签下查找h4标签
a_node = h4_node.find('a') # 查找a标签
print(a_node.text) # 打印出a标签内容
print(a_node['href']) # 打印出a标签链接(href属性的值)

成功解析出第一条新闻标题和链接:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

咦,情况不对,这个链接怎么看起来很别扭?而且只拿到第一条新闻,剩下的怎么办呢?继续修改代码:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin #从urllib库导入urljoin()函数,用于url拼接
response = requests.get('http://youxiputao.com/')
soup = BeautifulSoup(response.text, 'html.parser')
for li_node in soup.find('ul', {'class': 'news-list'}).find_all('li'): # 使用find_all()找出所有li标签,在for循环中解析每个标签
a_node = li_node.find('h4').find('a') # find()函数返回标签,可以连续查找;find_all()返回的是符合条件的所有标签的数组,需要循环遍历
title = a_node.text
href = a_node['href']
url = urljoin(response.url, href) # response.url是响应的地址,不一定是原始请求地址哦,因为网站可能会把对请求做重定向
print(url, title)

第一页采集成功:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

拿到了详情页面的链接,我们继续发送请求,采集详细数据。随便点开一个新闻页面,在chrome中按F12键查看页面结构:我们需要标题、时间、正文三部分,并把它们放在一个字典里来表示这条数据。

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

在刚才代码后面继续添加:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin # 从urllib库导入urljoin()函数,用于url拼接
response = requests.get('http://youxiputao.com/')
soup = BeautifulSoup(response.text, 'html.parser')
for li_node in soup.find('ul', {'class': 'news-list'}).find_all('li'): # 使用find_all()找出所有li标签,在for循环中解析每个
标签
a_node = li_node.find('h4').find('a') # find()函数返回标签,可以连续查找;find_all()返回的是符合条件的所有标签的数组,需要循环遍历
href = a_node['href']
url = urljoin(response.url, href) # response.url是响应的地址,不一定是原始请求地址哦,因为网站可能会把对请求做重定向
response_detail = requests.get(url) # 用response_detail 来区别之前的response
soup_detail = BeautifulSoup(response_detail.text, 'html.parser') # 继续解析
title = soup_detail.find('h2', class_='title').text # 可以用class_参数定位标签,仅限包含class、id等字段的标签,字典写法更通用
publish_time = soup_detail.find('div', {'class': 'pull-left'}).text # 直接获取div标签的“text”属性,包含div标签下所有子标签的文本
article = soup_detail.find('div', {'class': 'info-box col-sm-12'}).text
data = {'title': title, 'publish_time': publish_time, 'article': article}
print(data)

执行程序,采集结果如下:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

查看结果,发现有两个问题:

  1. 混进了奇怪的“\n”字符:\n是换行字符,对于字符串首位的空白字符(\n,\t,空格),可以使用strip()函数剔除。
  2. 图片去哪儿了:真实的爬虫项目通常不会采集图片,原因很简单:大型网站上千万数据,每条数据几张图片,再多硬盘都装不下。企业中对图片常用的处理方案:保存图片链接

继续修改刚才的代码:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
response = requests.get('http://youxiputao.com/')
soup = BeautifulSoup(response.text, 'html.parser')
for li_node in soup.find('ul', {'class': 'news-list'}).find_all('li'):
a_node = li_node.find('h4').find('a')
href = a_node['href']
url = urljoin(response.url, href)
response_detail = requests.get(url)
soup_detail = BeautifulSoup(response_detail.text, 'html.parser')
title = soup_detail.find('h2', class_='title').text
publish_time = soup_detail.find('div', {'class': 'pull-left'}).text.strip()
article = soup_detail.find('div', {'class': 'info-detail'}).text.strip() # strip()函数可以过滤字符串首尾的空白字符
images = [] # 用于存放文章中的图片
for img_node in soup_detail.find('div', {'class': 'info-detail'}).find_all('img'): # 找到文章主体节点,继续找到所有图片标签
img_url = img_node['src']
images.append(img_url)
cover = soup_detail.find('div', class_='cover').find('img')['src'] # 封面图片
images.append(cover)
data = {'title': title, 'publish_time': publish_time, 'images': images, 'article': article}
print(data)

看看修改后的采集结果:

《Python爬虫入门到入职02:编写第一个爬虫程序》
《Python爬虫入门到入职02:编写第一个爬虫程序》

图片有了,文章开头也没有含换行符了,感觉自己太牛X了!仔细查看字段内容,发现文章中间仍然包含\n,一般来说\n字符可以用来标识段落,不用处理。如果必须处理的话可以使用replace()函数:

article = article.replace('\n', '') # 使用“空字符”来替换“空白字符\n”,并重新赋值给article变量

最后,我们用面向对象的方式改写程序,完整代码如下:

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
class GameGrapeSpider: # 声明一个叫“GameGrapeSpider(游戏葡萄爬虫)”的类
def start(self): # 爬虫的启动函数
response = requests.get('http://youxiputao.com/')
soup = BeautifulSoup(response.text, 'html.parser')
for li_node in soup.find('ul', {'class': 'news-list'}).find_all('li'):
a_node = li_node.find('h4').find('a')
href = a_node['href']
url = urljoin(response.url, href)
response_detail = requests.get(url)
soup_detail = BeautifulSoup(response_detail.text, 'html.parser')
title = soup_detail.find('h2', class_='title').text
publish_time = soup_detail.find('div', {'class': 'pull-left'}).text.strip()
article = soup_detail.find('div', {'class': 'info-detail'}).text.strip()
images = [] # 用于存放文章中的图片
for img_node in soup_detail.find('div', {'class': 'info-detail'}).find_all('img'):
img_url = img_node['src']
images.append(img_url)
cover = soup_detail.find('div', class_='cover').find('img')['src'] # 封面图片
images.append(cover)
data = {'title': title, 'publish_time': publish_time, 'images': images, 'article': article}
print(data)
if __name__ == '__main__': # 程序入口,直接运行game_grape.py才执行,被导入时不会执行
spider = GameGrapeSpider() # 创建一个对象
spider.start() # 启动爬虫

课外练习:抓取以下网站的首页内容

  1. 3DM-新闻频道:标题、时间、来源、作者、编辑、文章、图片字段。
  2. 天天美剧-排行榜:名字、排名、海报(链接)、更新日、状态、分类、最后更新、回归日期、倒计时。

练习答案: Github地址

下一章 >> Python爬虫入门到入职03:全量抓取


推荐阅读
  • 本文由编程笔记#小编为大家整理,主要介绍了logistic回归(线性和非线性)相关的知识,包括线性logistic回归的代码和数据集的分布情况。希望对你有一定的参考价值。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • 解决Cydia数据库错误:could not open file /var/lib/dpkg/status 的方法
    本文介绍了解决iOS系统中Cydia数据库错误的方法。通过使用苹果电脑上的Impactor工具和NewTerm软件,以及ifunbox工具和终端命令,可以解决该问题。具体步骤包括下载所需工具、连接手机到电脑、安装NewTerm、下载ifunbox并注册Dropbox账号、下载并解压lib.zip文件、将lib文件夹拖入Books文件夹中,并将lib文件夹拷贝到/var/目录下。以上方法适用于已经越狱且出现Cydia数据库错误的iPhone手机。 ... [详细]
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • Python实现变声器功能(萝莉音御姐音)的方法及步骤
    本文介绍了使用Python实现变声器功能(萝莉音御姐音)的方法及步骤。首先登录百度AL开发平台,选择语音合成,创建应用并填写应用信息,获取Appid、API Key和Secret Key。然后安装pythonsdk,可以通过pip install baidu-aip或python setup.py install进行安装。最后,书写代码实现变声器功能,使用AipSpeech库进行语音合成,可以设置音量等参数。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • 本文详细介绍了MysqlDump和mysqldump进行全库备份的相关知识,包括备份命令的使用方法、my.cnf配置文件的设置、binlog日志的位置指定、增量恢复的方式以及适用于innodb引擎和myisam引擎的备份方法。对于需要进行数据库备份的用户来说,本文提供了一些有价值的参考内容。 ... [详细]
  • JavaScript设计模式之策略模式(Strategy Pattern)的优势及应用
    本文介绍了JavaScript设计模式之策略模式(Strategy Pattern)的定义和优势,策略模式可以避免代码中的多重判断条件,体现了开放-封闭原则。同时,策略模式的应用可以使系统的算法重复利用,避免复制粘贴。然而,策略模式也会增加策略类的数量,违反最少知识原则,需要了解各种策略类才能更好地应用于业务中。本文还以员工年终奖的计算为例,说明了策略模式的应用场景和实现方式。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 从零学Java(10)之方法详解,喷打野你真的没我6!
    本文介绍了从零学Java系列中的第10篇文章,详解了Java中的方法。同时讨论了打野过程中喷打野的影响,以及金色打野刀对经济的增加和线上队友经济的影响。指出喷打野会导致线上经济的消减和影响队伍的团结。 ... [详细]
  • 本文介绍了在Windows环境下如何配置php+apache环境,包括下载php7和apache2.4、安装vc2015运行时环境、启动php7和apache2.4等步骤。希望对需要搭建php7环境的读者有一定的参考价值。摘要长度为169字。 ... [详细]
  • Linux如何安装Mongodb的详细步骤和注意事项
    本文介绍了Linux如何安装Mongodb的详细步骤和注意事项,同时介绍了Mongodb的特点和优势。Mongodb是一个开源的数据库,适用于各种规模的企业和各类应用程序。它具有灵活的数据模式和高性能的数据读写操作,能够提高企业的敏捷性和可扩展性。文章还提供了Mongodb的下载安装包地址。 ... [详细]
author-avatar
婕小米
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有