获取网页源代码
- 使用urlopen函数
form urllib.request import urlopen url = "http://www.xxx.com" resp = urlopen(url) with open("xxx.html",mode="w",encoding="utf-8") as f: f.write(resp.read().decode("utf-8")) //基本都是utf-8或者gbk - url解析
from urllib import parse url = "http://www.baidu.com/123/333.html" img_url = "/111.html" new_url = parse.urljoin(url,img_url) # http://www.baidu.com/111.html 如果img_url以/开头,则urljoin会自动提取url的域名跟img_url拼接 如果img_url不以/开头,则urljoin会将333.html删除,再将img_url拼接
requests库 (是同步的)
- 安装: pip3 install requests
- 使用: import requests
- 设置headers: headers = {'User-Agent':'xxx'},防止反pa
- get方法:
- res = requests.get(url,params=params,headers=headers)
- res.text:拿到页面源代码
- res.json()
- res.encoding = 'utf-8':设置字符集
- post方法:
- res = requests.post(url,data = data)
- res.json()
- res.content: 这个是二进制内容,一般用于图片或视频的下载写入
- session:用来进行一连串的操作,比如需要cookie的url
- session = requests.session()
- 代理: `kuaidaili.com/free/intr/1/
proxy = { "http":"`http://xxx:port`", "https":"`https://xxx:port`" } resp = requests.get(url,proxies=proxy)
1.re模块(内置模块),用来提取分析数据的
-
findall(Regular:正则,要匹配的字符串)
import re result = re.findall(r'\d+',"123") 备注: 正则前加r,就可以不用关心里面的转义问题 -
finditer:返回迭代器,效率比findall高
result = finditer(r"\d+","1233哈333") for item in result: print(item.group()) #从匹配的结果中拿到数据 -
search: 只匹配第一次的匹配到的内容
-
match: 从字符串开头开始匹配
-
compile(正则):预加载,提前把正则对象加载完毕
-
分组查询
obj = re.compile(r'<div id='(?P<id>\d+)'>(?P<name>.*?)</div>') result = obj.finditer('字符串') for item in result: id = item.group('id') name = item.group('name') #?P<名称>正则: 这个是给分组起名字 -
?P<名称>正则: 这个是给分组起名字
-
re.S 可以让.能匹配到换行符
obj = re.compiler(r"正则",re.S) -
示例:
import requests import re url = "https://movie.douban.com/top250" f = open('doubanMoive.csv',mode='w',encoding='utf-8') headers = { "User-Agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36", "Cookie":'' } resp = requests.get(url,headers=headers) content = resp.text # re模块 regular = re.compile(r'<div class="item">.*?<span class="title">(?P<name>.*?)</span>' r'.*?导演:(?P<dao>.*?) ' r'.*?<br>(?P<year>.*?) ' r'.*?<span class="rating_num" property="v:average">(?P<score>.*?)</span>' r'.*?<span>(?P<num>.*?)人评价</span>', re.S) result = regular.finditer(content) for item in result: name = item.group('name') dao = item.group('dao') year = item.group('year').strip() score = item.group('score') num = item.group('num') f.write(f"电影名:{name},导演:{dao},年份:{year},评分:{score},评价人数:{num}\n") f.close() resp.close()
2. bs4库
- 安装: pip3 install bs4
- 引入: form bs4 import BeautifulSoup
- 初始化: page = BeautifulSoup(html字符串,"html.parse")
- 查找一个find: li = page.find("li",attrs={"属性名":"值"})
- 查找全部find_all
- 可以继续查找: a = li.find("a"); a.text;a.get("href")
获取数据
- 如果在获取子页面的href的字符串是以/开头,则用域名直接加上href
- 如果不是以/开头,则用当前页面的url,去掉当前url的最后一个/后面的内容,再拼接上href
- 这个可以使用from urllib import parse工具实现, new_url = parse.urljoin(url,src)
- 下载图片
img_resp = requests.get(img_url) with open('123.png',mode='wb') as f: f.write(img_resp.content)
3. xpath解析
- 安装 pip3 install lxml
- 导入 from lxml import etree 如果报错,则使用 form lxml import html;etree = html.etree
- 示例
xml = "xxxxxxx" et = etree.XML(xml) result = et.xpath("/app") # /表示根节点 result = et.xpath("/app/name") #找app下的直接后代name result = et.xpath("/app/name/text()") # name中的文本 result = et.xpath("/app//name") #找app下的子孙后代是name标签的 result = et.xpath("/app/*/name") #找app下的孙子是name标签的 result = et.xpath("/app/name[@class='abc']") #找app直接后代是name并且class=abc的 result = et.xpath("/app/name[2]") #找app直接后代是name标签并且是第2个 result = et.xpath("/app/name/@id") #拿到app直接后代是name标签的id result = li.xpath("./a") #拿到li下的a标签, ./表示当前路径
4. pyquery
- 安装 pip3 install pyquery
- 导入 from pyquery import PyQuery
- 使用
- p = PyQuery(html)
- p(选择器)
- p(选择器).items() 当选择的是多个标签的时候,返回迭代器
- attr(属性名)
- text() 只获取文本或子代文本
- html() 获取后代的所有html标签
- 修改属性
- p(选择器).after(PyQuery"
<div></div>") #在标签后添加标签,PyQuery加不加都行 - p(选择器).append("
<div></div>") #在标签内的最后添加标签 - p(选择器).attr("class","aaa") #新增/修改属性
- p(选择器).remove_attr("") #删除属性
- p(选择器).remove() #删除标签
- p(选择器:div > dl:nth-child(1) > dd).eq(0).text(): eq是从搜索到的结果集合里取第几个
- p(div> dl > dt:contains("有没有这个文字")): contains判断dt里面有没有这个文字
- p(选择器).after(PyQuery"