爬虫详细教程第2天

发布时间:2023年12月25日

各位小伙伴想要博客相关资料的话关注公众号:chuanyeTry即可领取相关资料!

1. 解析网页

解析网页的三种解析方式:

  • re解析
  • bs4解析
  • xpath解析

2.正则表达式

2.1概念

正则表达式, 一种使用表达式的方式对字符串进行匹配的语法规则.

正则的优点: 速度快, 效率高, 准确性高
正则的缺点: 新手上手难度有点儿高.

正则的语法: 使用元字符进行排列组合用来匹配字符串

在线测试正则表达式https://tool.oschina.net/regex/
链接: 在线测试正则表达式

元字符: 具有固定含义的特殊符号。

  • 常用元字符如下:
  • . 匹配除换行符以外的任意字符
  • \w 匹配字母或数字或下划线
  • \s 匹配任意的空白符
  • \d 匹配数字
  • \n 匹配一个换行符
  • \t 匹配一个制表符
  • ^ 匹配字符串的开始
  • $ 匹配字符串的结尾
  • \W 匹配非字母或数字或下划线
  • \D 匹配非数字
  • \S 匹配非空白符
  • a|b 匹配字符a或字符b
  • () 匹配括号内的表达式,也表示一个组
  • […] 匹配字符组中的字符
  • [^…]匹配除了字符组中字符的所有字符

量词: 控制前?的元字符出现的次数

  • 1.* 重复零次或更多次
  • 2.+ 重复一次或更多次
  • 3.? 重复零次或一次
  • 4.{n} 重复n次
  • 5.{n,} 重复n次或更多次
  • 6.{n,m} 重复n到m次

贪婪匹配和惰性匹配

  • .* 贪婪匹配
  • .*? 惰性匹配

3.re模块

  1. findall 查找所有. 返回list
lst = re.findall("m", "mai le fo len, mai nimei!")
print(lst) # ['m', 'm', 'm']
lst = re.findall(r"\d+", "5点之前. 你要给我 5000万")
print(lst) # ['5', '5000']
  1. search 会进行匹配. 但是如果匹配到了第一个结果. 就会返回这
    个结果. 如果匹配不上search返回的则是None
ret = re.search(r'\d', '5点之前. 你要给我 5000万').group()
print(ret) # 5
  1. match 只能从字符串的开头进行匹配
ret = re.match('a', 'abc').group()
print(ret) # a
  1. finditer, 和findall差不多. 只不过这时返回的是迭代器(重点)
it = re.finditer("m", "mai le fo len, mai ni mei!")
for el in it:
	print(el.group()) # 依然需要分组
  1. compile() 可以将一个正则进行预加载. 方便后面的使用
obj = re.compile(r'\d{3}') # 将正则表达式编译成为一个正则表达式对象, 规则要匹配的是3个数字
ret = obj.search('abc123eeee') # 正则表达式对象调用search, 参数为待匹配的字符串
print(ret.group()) # 结果: 123
  1. 正则中的内容如何单独提取?单独获取到正则中的具体内容可以给分组起名字
s = """
<div class='?游记'><span id='10010'>中国联通</span></div>
"""
obj = re.compile(r"<span id='(?P<id>\d+)'>(?P<name>\w+)</span>",re.S)
result = obj.search(s)
print(result.group()) # 结果: <spanid='10010'>中国联通</span>
print(result.group("id")) # 结果: 10010 # 获取id组的内容
print(result.group("name")) # 结果: 中国联通 #获取name组的内容

这里可以看到我们可以通过使用分组. 来对正则匹配到的内容进
一步的进行筛选.

4.豆瓣TOP250电影

目标: 抓取"电影名称",“上映年份”,“评分”,"评分人数"四项内容.怎么做呢?

首先, 先看一下页面源代码. 数据是否是在源代码上的?很明显, 我们想要的数据全部都在页面源代码中体现了. 接下来第一步了. 拿到?面源代码,然后呢. 从?面源代码中提取我们需要的内容. 这时候我们就可以去写正则了.

import requests
headers = {
"user-agent": "Mozilla/5.0 (Macintosh; IntelMac OS X 10_15_4)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
}
url = "https://movie.douban.com/top250?start=0&filter="
resp = requests.get(url, headers=headers)
print(resp.text)
obj = re.compile(r'<li>.*?<div class="item">.*?
<div class="pic">.*?<em class="">(?P<num>\d+)
</em>'
 r'.*?<span class="title">(?
P<name>.*?)</span>'
 r'.*?<p class="">.*?<br>\n(?
P<year>.*?)&nbsp;'
 r'.*?property="v:average">(?
P<average>.*?)</span>'
 r'.*?<span>(?P<people>\d+)?评价
</span>', re.S)

开始匹配, 将最终完整的数据按照自己喜欢(需要)的方式写入文件.

it = obj.finditer(resp.text)
with open("movie.csv", mode="w", encoding="utf-8") as f:
	csvwriter = csv.writer(f) # 创建csv文件写入工具,也可以直f.write()
	for item in it:
		dic = item.groupdict()
		dic['year'] = dic['year'].strip()
		csvwriter.writerow(dic.values()) # 写入数据

5.bs4解析-HTML语法

bs4解析比较简单, 但是呢, 首先你需要了解一丢丢的html知识. 然后再去使用bs4去提取, 因为bs4就是通过html标签和属性去定位?面上的内容的。

<body text="green" bgcolor="#eee">
你看我的颜色. 贼健康
</body>

<标签 属性=“值” 属性=“值”>
被标记的内容
</标签>

6.bs4解析-bs4模块安装和使用

6.1bs4模块安装

在python中我一般只推荐用pip进行安装. 原因: 简单!!!

pip install bs4

bs4在使用的时候就需要参照一些html的基本语法来进行使用了. 我们直接上案例. 案例是最能直观的展现出bs4的便捷效果的.

6.2bs4模块使用

我们来尝试抓取链接: link
http://www.xinfadi.com.cn/marketanalysis/0/list/1.shtml

老规矩, 先获取?面源代码. 并且确定数据就在?面源代码中~

import requests
from bs4 import BeautifulSoup
resp =
requests.get("http://www.xinfadi.com.cn/market
analysis/0/list/1.shtml")
print(resp.text)

将?面源代码丢给BeautifulSoup, 然后我们就可以通过bs对象去检索?面源代码中的html标签了

page = BeautifulSoup(resp.text)

BeautifulSoup对象获取html中的内容主要通过两个方法来完成

find()
find_all()

基本上有这两个方法就够用了. 不论是find还是find_all 参数几乎是一致的.
语法:

  • find(标签, 属性=值)

意思是在页面中查找 xxx标签, 并且标签的xxx属性必须是xxx值
例:find(‘div’, age=18) 含义: 在?面中查找div标签, 并且属性age必须是 18的这个标签.

find_all()的用法和find()几乎一致.
find()查找 1 个. ,find_all()查找?面中所有的.

<div class="honor">
page.find("div", class="honor")
注意, python中class是关键字. 会报错的. 怎么办呢? 可以在class后面加个下划线
page.find("div", class_="honor")

好了, 用法说完了. 接下来就回来看怎么抓取新发地的价格吧

table = page.find("table", class_="hq_table")
print(table)

接下来就可以进一步去提取数据了. 后面的直接给出完整代码.因为逻辑都是一样的. 并没有多么的复杂, 过程就省略了.

import requests
from bs4 import BeautifulSoup
import csv
resp =
requests.get("http://www.xinfadi.com.cn/marke
tanalysis/0/list/1.shtml")
page = BeautifulSoup(resp.text)
table = page.find("table", class_="hq_table")
f = open("新发地.csv", mode="w",
encoding="utf-8")
cv_writer = csv.writer(f)
# 提取到所有tr
tr_list = table.find_all("tr")[ 1 :] # 注意,第一
行并不是我想要的数据. (第一行是表头)
for tr in tr_list:
td_list = tr.find_all("td")
name = td_list[ 0 ].text # 获取文本内容
low = td_list[ 1 ].text
avg = td_list[ 2 ].text
high = td_list[ 3 ].text
gui = td_list[ 4 ].text
dan = td_list[ 5 ].text
day = td_list[ 6 ].text
cv_writer.writerow([name, low, avg, high,
gui, dan, day])
f.close()
print("搞定")

有人可能要问了. 为什么只有第一?数据. 你观察一下第二?, 第
三?的url就明白了了

http://www.xinfadi.com.cn/marketanalysis/ 0 /list/1.shtml
http://www.xinfadi.com.cn/marketanalysis/ 0 /list/2.shtml
http://www.xinfadi.com.cn/marketanalysis/ 0 /list/3.shtml

7.抓取图片

我们以优美图库作为本节课的案例。
链接:优美图库https://www.umei.cc/bizhitupian/weimeibizhi/

我需要在网站的首?中, 找到子?面的链接, 然后请求到子?面, 才能看到图片>也就是说, 想要下载该网站图片(高清大图), 需要三步,
第一步, 在主?面中拿到每一个图片的子?面链接
第二步, 在子?面中找到真正的图片下载地址
第三步, 下载图片

1.拿到子?面链接

def main_page():
	with open("child_page_href.txt", mode="w") as
f:
	for i in range( 1 , 56 ):
		try:
			resp =requests.get(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm")
			# <meta http-equiv="Content-Type"content="text/html; charset=utf-8" />
			resp.encoding = 'utf-8' # 处理中文乱码, 这里要和?面上的charset对应
			main_page =BeautifulSoup(resp.text, "html.parser")
			typeListDiv =main_page.find("div", attrs={"class":"TypeList"})
			main_a_list =typeListDiv.find_all("a")
			for main_a in main_a_list:
				href = main_a.get("href") #拿到某一个标签中xxx属性的值
				f.write(href)
				f.write("\n")
					print(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm, 成功了!")
			time.sleep(0.5)
		except:
			print(f"https://www.umei.cc/bizhitupian/weimeibizhi/{i}.htm, 出错了")
			print(resp.text)
			break # 也可以记录下来, 供以后查错用

2.获取到子页面信息, 找到下载图片的图片路径

def child_page():
	with open("child_page_href.txt", mode="r") as
f:
	for line in f:
		line = line.strip()
		resp = requests.get(line)
		resp.encoding='utf-8'
		child = BeautifulSoup(resp.text,"html.parser")
		div = child.find("div",class_="ImageBody")
		img = div.find("img")
		if img:
			src = img.get("src")
			print(src)
		else:
			print(line, "没有图片")
  1. 下载图片
def download_img(src):
	with open("img/"+src.split("/")[- 1 ],mode="wb") as f:
		resp = requests.get(src) # 下载图片
		f.write(resp.content) # 图片写入文件
		print(src, "down!")

最后运行一下, 看看结果对了一定记着把img文件夹设置为excluded, 否则你的pycharm会奇卡无比

文章来源:https://blog.csdn.net/hellow_xqs/article/details/135203456
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。