原创 麦自香 Python爬虫案例

当我们初学爬虫的时候,我们都会选择一些最基本的网站,往往不带任何反爬措施。比如某个博客站点,我们要爬全站的话,就顺着列表页爬到文章页,再把文章的时间、作者、正文等信息爬下来就可以了。那代码怎么写呢?

一般的情况我们都是使用 Python 的 requests 等库就够了,写一个基本的逻辑,顺着把一篇篇文章的源码获取下来,解析的话会用到 XPath、BeautifulSoup、或者正则表达式,再把文本写入存下来就完事了。代码很简单,就几个方法调用。逻辑很简单,几个循环加存储。

之所以这么说,是因为接下来我们想要对古诗文网站来进行爬取,分别用正则表达式、BeautifulSoup、Xpath、通过这些代码来给大家介绍下Python常用的选择器,以及他们之间的区别,让我们对Python的选择器有一个更深的认识。

一、正则表达式

正则表达式为我们提供了抓取数据的快捷方式。虽然该正则表达式更容易适应未来变化,但又存在难以构造、可读性差的问题。接下来我们使用正则表达式爬取古诗文网站,代码如下:

# 使用正则表达式解析网页元素

# 关键点:直接找每个个体里面相同位置的元素,用findall一次提取出来到列表中

import requests

import re

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def reParser(text):

name_list = re.findall(r'<div class="yizhu".*?<b>(.*?)</b>', text, re.S) # re.DOTALL

dynasty_list = re.findall(r'<p class="source">.*?target="_blank">(.*?)</a>', text, re.S)

author_list = re.findall(r'<p class="source">.*?target="_blank">.*?</a>.*?target="_blank">(.*?)</a>', text, re.S)

row_content_list = re.findall(r'<div class="contson".*?>(.*?)</div>', text, re.S)

content_list = []

for content in row_content_list:

temp = re.sub(r'<.*?>', '', content) # 这里一定要记得不要写成了贪婪匹配哦

content_list.append(temp.strip()) # 去除空格

for value in zip(name_list, dynasty_list, author_list, content_list):

name, dynasty, author, content = value

poetry_dict = {

'诗词名': name,

'朝代': dynasty,

'作者': author,

'内容': content,

}

DATA.append(poetry_dict)

def print_poetry(data):

for every_poetry in data:

print(every_poetry['诗词名'])

print(every_poetry['朝代'] + ':' + every_poetry['作者'])

print(every_poetry['内容'])

print("n" + '*' * 50 + "n")

if __name__ == '__main__':

row_url = '网页发生错误'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

num = input('请输入要爬取的页数(1-100):')

for i in range(eval(num)):

url = row_url.format(i + 1)

# print(url)

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

reParser(text)

TOP10 = DATA[:10]

# print(TOP10)

print_poetry(TOP10)

利用正则表达式实现对目标信息的精准采集,此外 ,我们都知道,网页时常会产生变更,导致网页中会发生一些微小的布局变化时,此时也会使得之前写好的正则表达式无法满足需求,而且还不太好调试。当需要匹配的内容有很多的时候,使用正则表达式提取目标信息会导致程序运行的速度减慢,需要消耗更多内存。

二、BeautifulSoup

BeautifulSoup是一个非常流行的 Pyhon 模块,简称Bs4。该模块可以解析网页,并提供定位内容的便捷接口。通过

pip install beautifulsoup4

就可以实现该模块的安装了。演示代码如下:

# 使用bs4提取网页,先利用find_all解析

import requests

from bs4 import BeautifulSoup

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def bs4_find_all_Parser(text):

soup = BeautifulSoup(text, 'lxml')

sons = soup.find_all('div', class_="sons")[:10] # 返回一个<class 'bs4.element.ResultSet'>,每一个元素都是Tag类型

# 注意:上一步里面返回了一些其他的元素,我们可以提取出前面的10项,那是我们需要用到的

# print(sons)

for son in sons:

name = son.find('b').get_text()

print(name)

dynasty_author = son.find('p', class_="source").get_text()

print(dynasty_author)

content = son.find('div', class_="contson").get_text()

print(content)

if __name__ == '__main__':

url = '古诗文网-古诗文经典传承'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

bs4_find_all_Parser(text)

使用 Bs4的第一步是将己下载的 HTML 内容解析为 soup文档。由于大多数网 页都不具备良好的HTML 格式,此Bs4需要对实际格式进行确定。Bs4能够正确解析缺失的引号并闭合标签,此外还会添加<html >和<body>标签使其成为完整的HTML文档。通常使用find() 和find_all()方法来定位我们需要的元素。

如果你想了解BeautifulSoup全部方法和参数,可以查阅BeautifulSoup的官方文档。虽然BeautifulSoup在代码的理解上比正则表达式要复杂一些,但是其更加容易构造和理解。

三、lxml

Xpath,使lxml 模块的第一步和BeautifulSoup一样,也是将有可能不合法的HTML 解析为统一格式。虽然lxml可以正确解析属性两侧缺失的引号,并闭合标签,不过该模块没有额外添加<html >和<body>标签 。

lxml也是需要提前安装的,通过:

pip install lxml

演示代码如下:

# xpath代码展示

import requests

from lxml import etree

DATA = []

def getHTMLtext(url, headers, timeout=10):

try:

resp = requests.get(url, headers=headers, timeout=timeout)

resp.raise_for_status

resp.encoding = 'utf-8'

return resp.text

except:

return ''

def xpathParser(text):

htmlElement = etree.HTML(text) # <class 'lxml.etree._Element'>

name_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[1]/a/b/text()')

dynasty_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[2]/a[1]/text()')

author_list = htmlElement.xpath('/html/body/div[2]/div[1]/div/div[1]/p[2]/a[2]/text()')

content_list = []

poetries = htmlElement.xpath(

'//div[@class="contson" and contains(@id,"contson")]') # 返回一个列表,里面每一个都是'lxml.etree._Element'

# print(etree.tostring(poetries[0],encoding = 'utf-8').decode('utf-8'))

for poetry in poetries:

row_content = ''.join(poetry.xpath('.//text()')) # 这里的.可千万不能掉,否则会忽略掉poetry哦

content_list.append(row_content.replace('n', ''))

for value in zip(name_list, dynasty_list, author_list, content_list):

name, dynasty, author, content = value

poetry_dict = {

'诗词名': name,

'朝代': dynasty,

'作者': author,

'内容': content,

}

DATA.append(poetry_dict)

def print_poetry(data):

for every_poetry in data:

print(every_poetry['诗词名'])

print(every_poetry['朝代'] + ':' + every_poetry['作者'])

print(every_poetry['内容'])

print("n" + '*' * 50 + "n")

if __name__ == '__main__':

row_url = '网页发生错误'

headers = {

'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'}

num = input('请输入要爬取的页数(1-100):')

for i in range(eval(num)):

url = row_url.format(i + 1)

text = getHTMLtext(url, headers)

if text == '':

print('url: {} 访问失败'.format(url))

else:

xpathParser(text)

TOP10 = DATA[:10]

print_poetry(TOP10)

在线复制Xpath表达式可以很方便的复制Xpath表达式。但是通过该方法得到的Xpath表达式放在程序中一般不能用,而且长的没法看。所以Xpath表达式一般还是要自己亲自上手。

如果你的爬虫瓶颈是下载网页,也不是抽取数据的话,那么使用较慢的方法(如BeautifulSoup) 也不成问题。如果只需抓取少量数据,并且想要避免额外依赖的话,那么正则表达式可能更加适合。不过,通常情况下,lxml是抓取数据的最好选择,这是因为该方法既快速又健壮,而正则表达式和BeautifulSoup只在某些特定场景下有用。

Lxml模块使用 C语言编写,其解析速度比 BeautiflSoup更快,而且其安装过程也更为复杂,在此小编就不赘述啦。XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

python list find_一篇文章带你了解Python爬虫常用选择器相关推荐

  1. 【Python发展前景】一篇文章带你了解Python未来发展“钱”景

    前言 计算机语言发展至今,已出现众多的编程语言.例如入门较难的C语言,相对通用的Java,适合初学者的Basic语言等. 但自从Python横空出世以来,以其简洁优美.功能强大.开发效率高等先天优势, ...

  2. excel中调用python程序_一篇文章带你使用Python搞定对Excel表的读写和处理

    文章目录一.我的需求二.代码三.总结 一.我的需求 我想要excel 的最后1列由列表形式转换为数值类型 ​ 可以看到最后一列有的是列表,有的直接是数值,想要整个列表中的内容都转为数值类型 二.代码 ...

  3. python人脸识别防小偷_一篇文章带你了解Python 人脸识别有多简单

    今天的Python学习教程给大家介绍一个世界上最简练的人脸辨认库 face_recognition,你可以应用 Python 和命令行工具进行提取.辨认.操作人脸. 基于业内领先的 C++ 开源库 d ...

  4. python人脸识别实验报告总结_一篇文章带你了解Python 人脸识别有多简单

    原标题:一篇文章带你了解Python 人脸识别有多简单 今天的Python学习教程给大家介绍一个世界上最简洁的人脸识别库 face_recognition,你可以使用 Python 和命令行工具进行提 ...

  5. 一篇文章带你了解webscraper爬虫插件

    点击上方"Python爬虫与数据挖掘",进行关注 回复"书籍"即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 夜阑卧听风吹雨,铁马冰河入梦来. ...

  6. 有没有python的班_【万字长文】别再报班了,一篇文章带你入门Python

    最近有许多小伙伴后台联系我,说目前想要学习Python,但是没有一份很好的资料入门.一方面的确现在市面上Python的资料过多,导致新手会不知如何选择,另一个问题很多资料内容也很杂,从1+1到深度学习 ...

  7. 万字长文,一篇文章带你入门Python

    注释 Python中用#表示单行注释,#之后的同行的内容都会被注释掉. 很多人学习python,不知道从何学起. 很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手. 很多已经做案例 ...

  8. 一篇文章带你了解Python中的游戏开发模块pyglet

    前言 为什么我不选择pygame,原因很简单,因为pyglet 更简单,比较轻量级,就好比django和flask的区别. 相信你在读了这篇文章之后也会毅然决然地选择pyglet. 这篇文章主要围绕p ...

  9. 一篇文章带你了解python装饰器

    一.什么是装饰器 所谓的装饰器,其实就是通过装饰器函数,来修改原函数的一些功能,使得原函数不需要修改. 这一句话理解起来可能没那么轻松,那先来看一个"傻瓜"函数. 放心,绝对不是& ...

最新文章

  1. 优词词根词典mdx_推荐|一波好用的在线英语词典网站
  2. 转帖 .Net(C#)纯GDI+绘制实时动态曲线图之二(曲线控件全部源码)
  3. 小学校园里计算机文字,中小学计算机教学论文(共2228字).doc
  4. [LeetCode] Intersection of Two Linked Lists 求两个链表的交点
  5. django ContentType使用方法
  6. Spring项目启动加载xml配置文件替换数据库提高响应速度
  7. JavaScript学习笔记(五)--深拷贝浅拷贝
  8. Flutter修仙传第一章:从Form入手学会组件使用
  9. linux上c语言hdc句柄,控制台窗口的绘图
  10. addLoadEvent方法解析
  11. [转]通过生日获取星座Python源码
  12. Python爬虫入门教程 29-100 手机APP数据抓取 pyspider
  13. boost::unorder_map如何插入元素_「leetcode」701. 二叉搜索树中的插入操作:【递归法】【迭代法】详解...
  14. android word文件编辑器,docx文档编辑
  15. FPGA与ASIC及SOC的区别?ARM是什么
  16. 夜晚网速变慢与网站服务器开机数量减少有关,网速变慢的原因及解决办法
  17. 前端开发和后端开发的区别
  18. 网站收录之采集新闻源工具
  19. android顶部按钮图片,安卓动态改变button顶部图片即drawableTop属性
  20. 链式线性表和顺序线性表

热门文章

  1. [moka同学笔记转载]Yii 设置 flash消息 创建一个渐隐形式的消息框
  2. 时间戳的转换和星期转换
  3. Ubuntu终端字体颜色方案
  4. Oracle的共享封闭 独占封闭和共享更新封闭 (1)
  5. Linux下如何生成core dump 文件(解决segment fault段错误的问题)
  6. [转]URL汉字编码问题(及乱码解决)
  7. 将HTMLCollection转换为数组的最有效方法
  8. 如何使用composer从Laravel中删除包?
  9. 如何修复“ sudo:不存在tty且未指定AskPass程序”错误?
  10. 从脚本本身获取Bash脚本的源目录