基于requests,bs4,re的简易爬虫
导入库
import re
import requests, bs4
爬取数据
res = requests.get('linkurl')
res.encoding = "utf-8"
#获取网页源代码
#dom = bs4.BeautifulSoup(res.text, features="html.parser")
#print(dom.prettify())
# 返回 http 的状态码
print(res.status_code)
# 响应状态的描述
print(res.reason)
# 返回编码
print(res.apparent_encoding)
# 返回 json 数据
print(res.json())
#正则匹配数据
issues_open=re.findall(fr''' (.*?) Open(.*?)''', res.text)
print('\n issues_open:' + str(issues_open))
requests, bs4
方法 | 描述 |
---|---|
delete(url, args) | 发送 DELETE 请求到指定 url |
get(url, params, args) | 发送 GET 请求到指定 url |
head(url, args) | 发送 HEAD 请求到指定 url |
patch(url, data, args) | 发送 PATCH 请求到指定 url |
post(url, data, json, args) | 发送 POST 请求到指定 url |
put(url, data, args) | 发送 PUT 请求到指定 url |
request(method, url, args) | 向指定的 url 发送指定的请求方法 |
带参访问
# 导入 requests 包
import requests
kw = {'s':'python 教程'}
# 设置请求头
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.99 Safari/537.36"}
# params 接收一个字典或者字符串的查询参数,字典类型自动转换为url编码,不需要urlencode()
response = requests.get("https://www.runoob.com/", params = kw, headers = headers)
# 查看响应状态码
print (response.status_code)
# 查看响应头部字符编码
print (response.encoding)
# 查看完整url地址
print (response.url)
# 查看响应内容,response.text 返回的是Unicode格式的数据
print(response.text)
访问结构
import requests, bs4
res = requests.get("http://xxxxx/crawl/crawlme.html")
print(res.status_code)
res.encoding = "utf-8"
dom = bs4.BeautifulSoup(res.text,features="html.parser")
print(dom.prettify())
print("###")
print(dom.table.tr.find_all("td"))
print(dom.table.tr.find_all("td")[-1])
print(dom.table.tr.find_all("td")[-1].a)
print(dom.table.tr.find_all("td")[-1].a["href"])
print("###")
print(type(dom.find(text="A02")))
print(dom.find(text="A02").parent["href"])
print(dom.ul.find_all("li"))
# print(dom.find_all(compile(r"^.l$")))
print(dom.find_all("option"))
print(dom.find("option", attrs={"value": "heiheihei"}).text)
循环替换
for page_price in range(1,7):
page_price_link=f"https://test.com/price-{page_price}.html"
res = requests.get(page_price_link)
res.encoding = "utf-8""
写入文件
handle=open("data1.txt","w",encoding = " utf-8 ")
for i in range(0,len(tmp1)):
handle.write(tmp1[i].tosqlstring()+"\n")
handle.close()
re
#re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
re.match(pattern, string, flags=0)
#匹配成功re.search方法返回一个匹配的对象,否则返回None。
re.search(pattern, string, flags=0)
#re.sub用于替换字符串中的匹配项
re.sub(pattern, repl, string, count=0, flags=0)
#在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表
re.findall(pattern, string, flags=0)
pattern.findall(string[, pos[, endpos]])
#在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
re.finditer(pattern, string, flags=0)
#split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
re.split(pattern, string[, maxsplit=0, flags=0])
#!/usr/bin/python3
import re
line = "Cats are smarter than dogs"
# .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
# (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
print ("matchObj.group() : ", matchObj.group())
print ("matchObj.group(1) : ", matchObj.group(1))
print ("matchObj.group(2) : ", matchObj.group(2))
else:
print ("No match!!")
字符串前 f r u b
f:
表示字符串内支持大括号内的python表达式,如:
logger.info(f"Total time taken: {time.time() - start_time}")
r:
去掉反斜杠的转移机制,如下面例子,表示单纯字符串而不表示换行
logger.info(r"Test\n\n\n")
u:
一般出现在中文字符串前,防止出现乱码
b:
表示这是一个bytes类型对象,在网络编程中,服务器和浏览器只认bytes类型数据,如:
response=b'<h1>Hello World</h1>'
避坑
-
不要直接从浏览器中复制网页源码,网页源码可能被浏览器修正
-
爬取网站注意登录状态与未登录状态代码可能不同
-
'''str '''
python多行字符串格式中,小心ide缩进问题,空格要为实际的空格数量,避免代码格式化带来的新的缩进空格出现
urllib
Python urllib 库用于操作网页 URL,并对网页的内容进行抓取处理
- urllib.request - 打开和读取 URL。
- urllib.error - 包含 urllib.request 抛出的异常。
- urllib.parse - 解析 URL。
- urllib.robotparser - 解析 robots.txt 文件。
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- url:url 地址。
- data:发送到服务器的其他数据对象,默认为 None。
- timeout:设置访问超时时间。
- cafile 和 capath:cafile 为 CA 证书, capath 为 CA 证书的路径,使用 HTTPS 需要用到。
- cadefault:已经被弃用。
- context:ssl.SSLContext类型,用来指定 SSL 设置。
from urllib.request import urlopen
myURL = urlopen("https://www.runoob.com/")
print(myURL.read())
#print(myURL.read(300)) 指定读取的长度
myURL = urlopen("https://www.runoob.com/")
print(myURL1.getcode()) # 200
print(myURL.readline()) #读取一行内容
myURL = urlopen("https://www.runoob.com/")
lines = myURL.readlines()
for line in lines:
print(line)
#将抓取的网页保存到本地
from urllib.request import urlopen
myURL = urlopen("https://www.runoob.com/")
f = open("runoob_urllib_test.html", "wb")
content = myURL.read() # 读取网页内容
f.write(content)
f.close()
URL 的编码与解码
#URL 的编码与解码可以使用 urllib.request.quote() 与 urllib.request.unquote() 方法
import urllib.request
encode_url = urllib.request.quote("https://www.runoob.com/") # 编码
print(encode_url)
unencode_url = urllib.request.unquote(encode_url) # 解码
print(unencode_url)
模拟头部信息
#模拟头部信息
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
- url:url 地址。
- data:发送到服务器的其他数据对象,默认为 None。
- headers:HTTP 请求的头部信息,字典格式。
- origin_req_host:请求的主机地址,IP 或域名。
- unverifiable:很少用整个参数,用于设置网页是否需要验证,默认是False。。
- method:请求方法, 如 GET、POST、DELETE、PUT等。
import urllib.request
import urllib.parse
url = 'https://www.runoob.com/?s=' # 菜鸟教程搜索页面
keyword = 'Python 教程'
key_code = urllib.request.quote(keyword) # 对请求进行编码
url_all = url+key_code
header = {
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
} #头部信息
request = urllib.request.Request(url_all,headers=header)
reponse = urllib.request.urlopen(request).read()
fh = open("./urllib_test_runoob_search.html","wb") # 将文件写入到当前目录中
fh.write(reponse)
fh.close()
提交表单
<form action="" method="post" name="myForm">
Name: <input type="text" name="name"><br>
Tag: <input type="text" name="tag"><br>
<input type="submit" value="提交">
</form>
import urllib.request
import urllib.parse
url = 'https://www.runoob.com/try/py3/py3_urllib_test.php' # 提交到表单页面
data = {'name':'RUNOOB', 'tag' : '菜鸟教程'} # 提交数据
header = {
'User-Agent':'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
} #头部信息
data = urllib.parse.urlencode(data).encode('utf8') # 对参数进行编码,解码使用 urllib.parse.urldecode
request=urllib.request.Request(url, data, header) # 请求处理
reponse=urllib.request.urlopen(request).read() # 读取结果
fh = open("./urllib_test_post_runoob.html","wb") # 将文件写入到当前目录中
fh.write(reponse)
fh.close()
ERROR
urllib.error 模块为 urllib.request 所引发的异常定义了异常类,基础异常类是 URLError。
urllib.error 包含了两个方法,URLError 和 HTTPError。
URLError 是 OSError 的一个子类,用于处理程序在遇到问题时会引发此异常(或其派生的异常),包含的属性 reason 为引发异常的原因。
HTTPError 是 URLError 的一个子类,用于处理特殊 HTTP 错误例如作为认证请求的时候,包含的属性 code 为 HTTP 的状态码, reason 为引发异常的原因,headers 为导致 HTTPError 的特定 HTTP 请求的 HTTP 响应头。
import urllib.request
import urllib.error
myURL1 = urllib.request.urlopen("https://www.runoob.com/")
print(myURL1.getcode()) # 200
try:
myURL2 = urllib.request.urlopen("https://www.runoob.com/no.html")
except urllib.error.HTTPError as e:
if e.code == 404:
print(404) # 404
解析URL
#urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
from urllib.parse import urlparse
o = urlparse("https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B")
print(o)
urlstring 为 字符串的 url 地址,scheme 为协议类型,
allow_fragments 参数为 false,则无法识别片段标识符。相反,它们被解析为路径,参数或查询组件的一部分,并 fragment 在返回值中设置为空字符串。
属性 | 索引 | 值 | 值(如果不存在) |
---|---|---|---|
scheme |
0 | URL协议 | scheme 参数 |
netloc |
1 | 网络位置部分 | 空字符串 |
path |
2 | 分层路径 | 空字符串 |
params |
3 | 最后路径元素的参数 | 空字符串 |
query |
4 | 查询组件 | 空字符串 |
fragment |
5 | 片段识别 | 空字符串 |
username |
用户名 | None |
|
password |
密码 | None |
|
hostname |
主机名(小写) | None |
|
port |
端口号为整数(如果存在) | None |
robotparser
urllib.robotparser 用于解析 robots.txt 文件。
robots.txt(统一小写)是一种存放于网站根目录下的 robots 协议,它通常用于告诉搜索引擎对网站的抓取规则。
class urllib.robotparser.RobotFileParser(url='')
- set_url(url) - 设置 robots.txt 文件的 URL。
- read() - 读取 robots.txt URL 并将其输入解析器。
- parse(lines) - 解析行参数。
- can_fetch(useragent, url) - 如果允许 useragent 按照被解析 robots.txt 文件中的规则来获取 url 则返回 True。
- mtime() -返回最近一次获取 robots.txt 文件的时间。 这适用于需要定期检查 robots.txt 文件更新情况的长时间运行的网页爬虫。
- modified() - 将最近一次获取 robots.txt 文件的时间设置为当前时间。
- crawl_delay(useragent) -为指定的 useragent 从 robots.txt 返回 Crawl-delay 形参。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
- request_rate(useragent) -以 named tuple RequestRate(requests, seconds) 的形式从 robots.txt 返回 Request-rate 形参的内容。 如果此形参不存在或不适用于指定的 useragent 或者此形参的 robots.txt 条目存在语法错误,则返回 None。
- site_maps() - 以 list() 的形式从 robots.txt 返回 Sitemap 形参的内容。 如果此形参不存在或者此形参的 robots.txt 条目存在语法错误,则返回 None。
Q.E.D.