本文最后更新于 2025-04-29T11:40:05+08:00
爬虫
简单概念 网络爬虫:模拟浏览器发送网络请求,接受请求响应,一种按一定规则,自动地抓取互联网信息的程序
Preparation
可以使用python
一些可能使用到的库:1 2 3 4 5 6 7 from bs4 import BeautifulSoup import re import urllib.request, urllib.error import xlwt
# coding=utf-8
或 # -*- coding: utf-8 -*-
来指定源代码的编码方式,防止乱码
大体流程
爬取网页
逐一解析数据
保存网页
详细展开 爬取网页:
1 2 for i in range (0 , 10 ): url = baseurl + str (i * 25 )
baseurl是要爬虫的网址,加上的str(i*25)是用于 翻页 ,通过这样子设置可以跳转到不同的界面
askURL()
用于请求网页
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 def askURL (url ): head = { "User-Agent" : "Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 80.0.3987.122 Safari / 537.36" } request = urllib.request.Request(url, headers=head) html = "" try : response = urllib.request.urlopen(request) html = response.read().decode("utf-8" ) except urllib.error.URLError as e: if hasattr (e, "code" ): print (e.code) if hasattr (e, "reason" ): print (e.reason) return html
head用于模拟浏览器头部信息,相当于我们在模拟人工查询网页时目标服务器会接受到的信息
如果不写head可能会被认出来是爬虫,导致错误
逐一解析数据:
解析数据用到了BeautifulSoup这个库(爬虫必备库)
用正则表达式去匹配:
1 2 3 4 5 6 7 findLink = re.compile (r'<a href="(.*?)">' ) findImgSrc = re.compile (r'<img.*src="(.*?)"' , re.S) findTitle = re.compile (r'<span class="title">(.*)</span>' ) findRating = re.compile (r'<span class="rating_num" property="v:average">(.*)</span>' ) findJudge = re.compile (r'<span>(\\d*)人评价</span>' ) findInq = re.compile (r'<span class="inq">(.*)</span>' ) findBd = re.compile (r'<p class="">(.*?)</p>' , re.S)
一些解释:
r''
:用于表示python的原始字符串,避免 \\
作为转义符干扰,让正则表达式更易读
<p class="">
这里匹配 <p>
标签,要求 class
属性为空
如果网页class属性省略了,还需要调整匹配方式
(.*?)
小括号表示一个捕获组,可以提取匹配到的内容
.*?
:
.
匹配任意字符
*?
非贪婪匹配,匹配尽可能少的字符,遇到 </p>
(结束标签)就停止
*
表示匹配任意次数,但 ?
让它变成非贪婪模式
re.S
(re.DOTALL
)
让 .
可以匹配换行符,<p>
标签内部文本可以是多行的
如果没有 re.S
,换行符 \\n
可能会导致匹配失败
保存数据:
1 2 saveData(datalist,savepath)
保存数据可以选择保存到 xls表(xlwt库支持),或者保存到sqlite数据库(sqlite3库支持)
1 2 3 4 5 6 7 8 9 10 11 12 13 def saveData (datalist,savepath ): print ("save......." ) book = xlwt.Workbook(encoding="utf-8" ,style_compression=0 ) sheet = book.add_sheet('豆瓣电影Top250' , cell_overwrite_ok=True ) col = ("电影详情链接" ,"图片链接" ,"影片中文名" ,"影片外国名" ,"评分" ,"评价数" ,"概况" ,"相关信息" ) for i in range (0 ,8 ): sheet.write(0 ,i,col[i]) for i in range (0 ,250 ): data = datalist[i] for j in range (0 ,8 ): sheet.write(i+1 ,j,data[j]) book.save(savepath)
sheet = book.add_sheet('豆瓣电影Top250', cell_overwrite_ok=True) #创建工作表
创建工作表
col = ("电影详情链接","图片链接","影片中文名","影片外国名","评分","评价数","概况","相关信息")
创建列
But!这个xls有点老旧的样子,在vscode和wps都没办法打开文件,所以叫ai重写了一下。改为使用openpyxl库
1 2 3 4 5 6 7 8 9 10 11 12 13 def saveData (datalist, savepath ): print ("正在保存数据......" ) wb = openpyxl.Workbook() sheet = wb.active sheet.title = "豆瓣电影Top250" col = ["电影详情链接" , "图片链接" , "影片中文名" , "影片外国名" , "评分" , "评价数" , "概况" , "相关信息" ] sheet.append(col) for data in datalist: sheet.append(data) wb.save(savepath)
开展: (一)分析目标网站
在编写爬虫前,先查看目标网站的robots.txt文件,了解网站允许的爬取范围。同时,使用浏览器开发者工具(F12)检查页面结构,分析数据所在位置和标签特征。
(二)发送请求
利用工具向目标网站发送HTTP请求,获取网页内容。在发送请求时,要注意设置合适的请求头,模拟真实浏览器行为,避免被网站识别为爬虫。
(三)解析内容
将获取到的网页内容进行解析,提取所需数据。根据网页结构和数据特点,选择合适的解析工具和方法。
(四)存储数据
将提取到的数据存储到本地文件或数据库中,方便后续使用和分析。根据数据量和使用需求,选择合适的存储方式。
(五)处理动态内容
对于动态生成的网页内容,需要使用专门的工具模拟浏览器操作,获取完整的页面数据。在处理动态内容时,要注意页面加载时间和操作的稳定性。
(六)反爬策略应对
网站为了保护自身数据,会采取各种反爬措施。可以通过设置请求头、使用代理IP、添加延迟等方式应对反爬策略,确保爬虫的稳定运行。
Requests库 七个主要方法 req.request()
构造一个请求
req.get()
获取HTML网页
req.head()
获取HTML网页头信息
req.post()
向HTML网页提交POST请求
req.put()
提交PUT请求
req.patch()
提交局部修改请求
req.delete()
提交删除请求
正则表达式 $ 表示结束匹配
元字符
含义
示例
.
匹配任意 一个字符(除了换行符 \\n
)
a.b
匹配 "acb"
、"a2b"
^
匹配行首
^abc
只能匹配 "abc"
在字符串开头的情况
$
匹配行尾
xyz$
只能匹配 "xyz"
在字符串结尾的情况
*
匹配0 或多次 前面的字符
ab*c
匹配 "ac"
、"abc"
、"abbc"
+
匹配1 或多次 前面的字符
ab+c
匹配 "abc"
、"abbc"
,但不匹配 "ac"
?
匹配0 或 1 次 前面的字符
ab?c
匹配 "ac"
和 "abc"
{m,n}
匹配m 到 n 次 前面的字符
ab{1,3}c
匹配 "abc"
、"abbc"
、"abbbc"
符号
含义
示例
\\d
匹配数字 (等价于 [0-9]
)
\\d+
匹配 "123"
\\D
匹配非数字 (等价于 [^0-9]
)
\\D+
匹配 "abc"
\\w
匹配单词字符 (字母、数字、下划线 a-zA-Z0-9_
)
\\w+
匹配 "hello123"
\\W
匹配非单词字符 (等价于 [^a-zA-Z0-9_]
)
\\W+
匹配 "$#@"
\\s
匹配空白字符 (空格、Tab、换行)
\\s+
匹配 " "
\\S
匹配非空白字符
\\S+
匹配 "hello"
.*
默认匹配尽可能多 的字符:默认为贪婪匹配
使用 *?
或 +?
让匹配 尽可能少 :非贪婪匹配
Python 正则表达式常用方法
方法
功能
re.match(pattern, string)
从头 匹配字符串
re.search(pattern, string)
搜索 第一个匹配项
re.findall(pattern, string)
返回所有匹配项 (列表)
re.finditer(pattern, string)
以迭代器返回所有匹配项
re.sub(pattern, repl, string)
替换 匹配项
re.split(pattern, string)
分割 字符串
用爬虫爬idol的照片 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 import requestsfrom bs4 import BeautifulSoupimport timeimport randomimport osdef fetch_images (keyword, num_images=10 ): user_agents = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' , 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0.3 Safari/605.1.15' , 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0' , 'Mozilla/5.0 (iPhone; CPU iPhone OS 14_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.0 Mobile/15E148 Safari/604.1' ] session = requests.Session() url = f'<https://cn.bing.com/images/search?q={keyword} &form=HDRSC2&first=1>' headers = { 'User-Agent' : random.choice(user_agents), 'Referer' : '<https://cn.bing.com/>' } try : print ("开始发送请求..." ) response = session.get(url, headers=headers, timeout=10 ) response.raise_for_status() print ("请求成功,状态码:" , response.status_code) except requests.exceptions.RequestException as e: print (f'请求失败: {e} ' ) return soup = BeautifulSoup(response.text, 'html.parser' ) image_urls = [] for img in soup.find_all('img' , class_='mimg' ): img_url = img.get('src' ) if img_url and img_url.startswith(('http://' , 'https://' )): image_urls.append(img_url) if not os.path.exists('images' ): os.makedirs('images' ) for i, img_url in enumerate (image_urls[:num_images]): try : time.sleep(random.uniform(2 , 5 )) headers['User-Agent' ] = random.choice(user_agents) print (f"开始下载图片 {i+1 } : {img_url} " ) response = session.get(img_url, headers=headers, timeout=10 ) response.raise_for_status() with open (f'images/image_{i} .jpg' , 'wb' ) as f: f.write(response.content) print (f'下载完成: image_{i} .jpg' ) except requests.exceptions.RequestException as e: print (f'下载失败: {e} ' )def main (): keyword = '姚琛' num_images = 10 print (f"开始抓取 {num_images} 张 '{keyword} ' 的图片..." ) fetch_images(keyword, num_images) print ("程序运行结束。" )if __name__ == "__main__" : main()
结果:
笔记参考&资料:
https://blog.csdn.net/bookssea/article/details/107309591
https://www.runoob.com/python3/python-spider-beautifulsoup.html
https://github.com/Ehco1996/Python-crawler?tab=readme-ov-file