선수 과목 : 특정 파이썬 기초를 배운 후 웹 크롤러의 내용을 계속 배울 수 있습니다. 파이썬 기본 문법 학습이 없다면 파이썬 기본 문법 노트 요약 을 찾아볼 수 있습니다 .
1. 웹 크롤러의 규칙
1. 요청 라이브러리 시작하기
방법 | 설명하다 |
---|---|
요청.요청() | 다음 메서드의 기본 메서드를 지원하는 요청을 구성합니다. |
요청.get() | HTTP get에 해당하는 HTML 페이지를 얻는 주요 방법 |
요청.헤드() | HTTP 헤더에 해당하는 HTML 페이지의 헤더 정보를 가져오는 메소드 |
요청.포스트() | HTTP 게시물에 해당하는 HTML 페이지에 POST 요청을 제출하는 방법 |
요청.put() | HTTP put에 해당하는 HTML 페이지에 PUT 요청 메소드 제출 |
요청.패치() | HTTP 패치에 해당하는 HTML 페이지에 부분 수정 요청 제출 |
요청.삭제() | HTTP 삭제에 해당하는 HTML 페이지에 삭제 요청 제출 |
1.1, get() 메서드
r = requests.get(url) #构造一个向服务器请求资源的Request对象,返回一个Resopnse对象r
requests.get(url,params=없음,**kwargs)
url : 취득하고자 하는 페이지의 url 링크
params : URL, 사전 또는 바이트 스트림 형식의 추가 매개변수, 선택사항
* * kwargs : 접근을 제어하는 12개의 매개변수
속성 | 설명하다 |
---|---|
r.status_code | HTTP 요청의 반환 상태, 200은 연결 성공, 404는 실패를 의미합니다. |
r.text | HTTP 응답 내용의 문자열 형식, 즉 url에 해당하는 페이지 내용 |
r.인코딩 | HTTP 헤더에서 응답 콘텐츠 인코딩 추측 |
r.appparent_encoding | 콘텐츠에서 구문 분석할 응답 콘텐츠 인코딩(대체 인코딩) |
내용 | HTTP 응답 콘텐츠의 바이너리 형식 |
참고 : r.encoding: 헤더에 charset이 없으면 인코딩은 ISO-8859-1로 간주되어 중국어를 파싱할 수 없습니다. r.encoding을 올바르게 디코딩할 수 없는 경우 r.apparent_encoding을 사용하고 획득한 인코딩을 r.encoding에 할당해야 올바르게 구문 분석될 수 있습니다.
#爬取案例
import requests
r = requests.get("http://www.baidu.com")
print(r.status_code) #状态码200
print(r.encoding) #ISO-8859-1
# print(r.text) 不能成功解码
print(r.apparent_encoding)#utf-8
r.encoding = 'utf-8' #修改编码方式
print(r.text) #成功获取
1.2, 라이브러리 예외 요청
이상 | 설명하다 |
---|---|
요청.연결 오류 | DNS 쿼리 실패, 연결 거부 등의 비정상적인 네트워크 연결 오류 |
요청.HTTP오류 | HTTP 오류 예외 |
요청.URL필수 | URL 누락 예외 |
requests.TooMany리디렉션 | 최대 리디렉션 수를 초과하면 리디렉션 예외가 생성됩니다. |
요청.ConnectTimeout | 원격 서버 연결 시간 초과 예외 |
요청.시간 초과 | 요청 URL 시간이 초과되어 시간 초과 예외가 발생했습니다. |
1.3 웹 페이지 크롤링을 위한 일반 코드 프레임워크
import requests
def getHTMLText(url):
try:
r = requests.get(url,timeout=30)
r.raise_for_status() #如果状态不是200,引发HTTPError异常
r.encoding = r.apparent_encoding
return r.text
except:
return "产生异常"
if __name__ == "__main__":
url = "http://www.baidu.com" #选择爬取的网页
print(getHTMLText(url))
1.4, HTTP 프로토콜
HTTP 프로토콜은 하이퍼텍스트 전송 프로토콜입니다.
HTTP는 "요청 및 응답" 모델을 기반으로 하는 상태 비저장 응용 프로그램 계층 프로토콜입니다.
리소스에 대한 HTTP
방법 | 설명하다 |
---|---|
가져 오기 | URL 위치에서 리소스 가져오기 요청 |
머리 | URL 위치 리소스의 응답 메시지 보고서 가져오기 요청, 즉 리소스의 헤더 정보 가져오기 |
게시하다 | URL 위치의 리소스에 요청 후 새 데이터 추가 |
놓다 | URL 위치에 리소스를 저장하도록 요청하고 원래 URL 위치에 리소스를 덮어씁니다. |
반점 | URL 위치에서 리소스의 부분 업데이트를 요청합니다. 즉, 리디렉션된 리소스 콘텐츠의 일부를 변경합니다. |
삭제 | URL 위치에 저장된 리소스 삭제 요청 |
1.5, 요청 라이브러리의 주요 분석
requests.request(method,url,**kwargs)
방법 : 요청 방법, 1.4의 6가지 유형 참조
* * kwargs : 접근을 제어하는 매개변수, 모두 선택사항
매개변수 유형 | 설명하다 |
---|---|
매개변수 | 사전 또는 바이트 시퀀스, url을 매개변수로 추가 |
데이터 | 요청의 내용으로 사전, 바이트 시퀀스 또는 파일 객체 |
json | Request의 내용으로 JSON 형식의 데이터 |
헤더 | 사전, HTTP 사용자 정의 헤더 |
쿠키 | 사전 또는 CookieJar, 요청의 쿠키 |
인증 | Tuple, HTTP 인증 기능 지원 |
파일 | 사전 유형, 전송 파일 |
시간 초과 | 시간 초과 시간을 초 단위로 설정 |
프록시 | 사전 유형, 액세스 프록시 서버 설정, 로그인 인증 추가 가능 |
2. 로봇 프로토콜
기능: 웹사이트는 크롤러에게 크롤링할 수 있는 것과 크롤할 수 없는 것을 알려줍니다.
형식: 웹사이트의 루트 디렉토리에 있는 robots.txt 파일
예: http://www.baidu.com/robots.txt
로봇 프로토콜 사용 :
웹 크롤러: robots.txt를 자동 또는 수동으로 식별하고 콘텐츠를 크롤링합니다.
구속력: 로봇 계약이 권장되지만 구속력이 없습니다. 웹 크롤러가 이를 준수하지 않을 수 있지만 법적 위험이 있습니다.
3, 라이브러리 웹 크롤러 전투 요청
웹사이트 방문을 위한 브라우저 시뮬레이션:
kv = {
"user-agent":"Mozilla/5.0"}
url = ""
r = requests.get(url,headers = kv)
3.1, 바이두 검색 키워드
import requests
# 百度搜索关键字提交:
# 百度搜索关键字格式:http://www.baidu.com/s?wd=关键字
kv = {
"wd":"Python"} #输入需要查询的关键字
r = requests.get("http://www.baidu.com/s",params=kv)
print(r.status_code)
print(r.request.url) #查询提交的url是否为想提交的
print(len(r.text)) #查询有多少长度
3.2 네트워크 이미지 크롤링 및 저장
import requests
import os
url = "http://img0.dili360.com/pic/2022/03/28/624109135e19b9603398103.jpg"
root = "D://pics//"
path = root + url.split('/')[-1]
try:
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
r = requests.get(url)
with open(path,"wb") as f:
f.write(r.content)
f.close()
print("文件保存成功")
else:
print("文件已存在")
except:
print("爬取失败")
2. 웹 크롤러 추출
1. Beautiful Soup 라이브러리 이용
from bs4 import BeautifulSoup
soup = BeautifulSoup(mk,"html.parser")
1.1 기본 요소
Beautiful Soup 라이브러리 파서
파서 | 지침 | 상태 |
---|---|---|
bs4용 HTML 파서 | BeautifulSoup(mk,“html.parser”) | bs4 라이브러리 설치 |
lxml的HTML解析器 | BeautifulSoup(mk,“lxml”) | pip install lxml |
lxml的XML解析器 | BeautifulSoup(mk,“xml”) | pip install lxml |
html5lib的解析器 | BeautifulSoup(mk,“html5lib”) | pip install html5lib |
Beautiful Soup类的基本元素
基本元素 | 说明 |
---|---|
Tag | 标签,最基本的信息组织单元,分别使用<>和</>标明开头和结尾 |
Name | 标签的名字, … 的名字是’p’,格式:.name |
Attributes | 标签的属性,字典形式组织,格式:.attrs |
NavigableString | 标签内非属性字符串,<>…</>中字符串,格式:.string |
Comment | 标签内字符串的注释部分,一种特殊的Comment类型 |
1.2、基于bs4库的HTML内容遍历方法
标签树的下行遍历
属性 | 说明 |
---|---|
.contents | 子节点的列表,将所有儿子节点存入列表 |
.children | 子节点的迭代类型,与.contents类似,用于循环遍历儿子节点 |
.descendants | 子孙节点的迭代类型,包含所有子孙节点,用于循环遍历 |
标签树的下行遍历
属性 | 说明 |
---|---|
.parent | 节点的父亲标签 |
.parents | 节点先辈标签的迭代类型,用于循环遍历先辈节点 |
标签树的平行遍历
属性 | 说明 |
---|---|
.next_sibling | 返回按照HTML文本顺序的下一个平行节点标签 |
.previous_sibling | 返回按照HTML文本顺序的上一个平行节点标签 |
.next_siblings | xu迭代类型,返回按照HTML文本顺序的后续所有平行节点标签 |
.previous_siblings | 迭代类型,返回按照HTML文本顺序的前续所有平行节点标签 |
1.3、基于bs4库的HTML格式化和编码
prettify():在html后自动增加换行,更好的观察标签树
默认编码格式:utf-8
2、信息组织与提取方法
2.1、信息标记
信息的标记
标记后的信息可形成信息组织结构,增加了信息维度
标记后的信息可用于通信、存储或展示
标记结构与信息一样具有重要价值
标记后的信息更利于程序的理解和应用
XML:最早的通用信息标记语言,可扩展性好,但繁琐
JSON:信息有类型,适合程序处理(js),较XML简洁
YAML:信息无类型,文本信息比例最高,可读性好
2.2、信息提取的一般方法
方法一:完整解析信息的标记形式,再提取关键信息
需要标记解析器,例如:bs4库的标签树遍历
优点:信息解析准确
缺点:提取过程繁琐,速度慢
方法二:无视标记形式,直接搜索关键信息
对信息的文本查找函数即可。
优点:提取过程简洁,速度较快
缺点:提取结果准确性与信息内容相关
融合方法:结合形式解析与搜索方法,提取关键信息。
需要标记解析器及文本查找函数
实例:提取HTML中所有的URL链接
思路:搜索到所有的标签,解析标签格式,提取href后的链接内容。
import requests
from bs4 import BeautifulSoup
r = requests.get("http://python123.io/ws/demo.html")
demo = r.text
soup = BeautifulSoup(demo,"html.parser")
for link in soup.find_all('a'):
print(link.get('href'))
2.3、基于bs4库的HTML内容查找方法
<>.find_all(name, atrs, recursive, string, **kwargs)
返回一个列表类型,存储查找的结果
name:对标签名称的索引字符串。
attrs:对标签属性值的检索字符串,可标记属性检索
recursive:是否对子孙全部检索,默认True
string:<>…</>中字符串区域的检索字符串
(…) 等价于 .find_all(…)
soup(…) 等价于 soup.find_all(…)
3、实例:大学排名信息
import bs4
import requests
from bs4 import BeautifulSoup
def getHTMLText(url):
'''获取网页的文本'''
try:
r = requests.get(url, timeout=30)
r.raise_for_status() # 如果状态不是200,引发HTTPError异常
r.encoding = r.apparent_encoding
return r.text
except:
return ""
def fillUnivList(ulist,html):
'''解析需要的文本,放入到列表中'''
soup = BeautifulSoup(html,"html.parser")
for tr in soup.find('tbody').children:
if isinstance(tr,bs4.element.Tag):
tds = tr('td')
ulist.append([tds[0].string.strip('\n '),tds[1].a.string,tds[4].string.strip('\n ')])
def printUnivLIist(ulist,num):
'''按格式化输出'''
tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
print(tplt.format("排名","学校名称","总分",chr(12288)))
for i in range(num):
u = ulist[i]
print(tplt.format(u[0],u[1],u[2],chr(12288)))
def main():
uinfo = []
url = "https://www.shanghairanking.cn/rankings/bcur/2022"
html = getHTMLText(url)
fillUnivList(uinfo,html)
printUnivLIist(uinfo,30)
main()