基于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。