本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理
以下文章来源于凌晨安全,作者 MoLing

1. 爬虫就是模拟浏览器抓取东西,爬虫三部曲:数据爬取、数据解析、数据存储
数据爬取:手机端、pc端数据解析:正则表达式数据存储:存储到文件、存储到数据库
2. 相关python库
爬虫需要两个库模块:requests和re
1. requests库
requests是比较简单易用的HTTP库,相较于urllib会简洁很多,但由于是第三方库,所以需要安装,文末附安装教程链接(链接全在后面,这样会比较方便看吧,贴心吧~)
requests库支持的HTTP特性:
保持活动和连接池、Cookie持久性会话、分段文件上传、分块请求等
Requests库中有许多方法,所有方法在底层的调用都是通过request()方法实现的,所以严格来说Requests库只有request()方法,但一般不会直接使用request()方法。以下介绍Requests库的7个主要的方法:
①requests.request()
构造一个请求,支撑一下请求的方法
具体形式:requests.request(method,url,**kwargs)
method:请求方式,对应get,post,put等方式
url:拟获取页面的url连接
**kwargs:控制访问参数
②requests.get()
获取网页HTM网页的主要方法,对应HTTP的GET。构造一个向服务器请求资源的Requests对象,返回一个包含服务器资源的Response对象。
Response对象的属性:

具体形式:res=requests.get(url)
code=res.text (text为文本形式;bin为二进制;json为json解析)
③requests.head()
获取HTML的网页头部信息,对应HTTP的HEAD
具体形式:res=requests.head(url)
④requests.post()
向网页提交post请求方法,对应HTTP的POST
具体形式:res=requests.post(url)
⑤requests.put()
向网页提交put请求方法,对应HTTP的PUT
⑥requests.patch()
向网页提交局部修改的请求,对应HTTP的PATCH
⑦requests.delete()
向网页提交删除的请求,对应HTTP的DELETE
# requests 操作练习 import requests import re #数据的爬取 h = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36' } response = requests.get('https://movie.douban.com/chart',headers=h) html_str = response.text #数据解析<a href="https://movie.XX.com/subject/34961898/" title="汉密尔顿"> pattern = re.compile('<a.*?title="(.*?)">') # .*? 任意匹配尽可能多的匹配尽可能少的字符 result = re.findall(pattern,html_str) print(result)
2. re正则表达式:(Regular Expression)
一组由字母和符号组成的特殊字符串,作用:从文本中找到你想要的格式的句子
关于 .*? 的解释:

3. xpath解析源码
import requests import re from bs4 import BeautifulSoup from lxml import etree #数据爬取(一些HTTP头的信息) h = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36' } response = requests.get('https://movie.XX.com/chart',headers=h) html_str = response.text #数据解析 #正则表达式解析 def re_parse(html_str): pattern = re.compile('<a.*?title="(.*?)"') results = re.findall(pattern,html_str) print(results) return results #bs4解析 def bs4_parse(html_str): soup = BeautifulSoup(html_str,'lxml') items = soup.find_all(class_='nbg') for item in items: print(item.attrs['title']) #lxml解析 def lxml_parse(html_str): html = etree.HTML(html_str) results = html.xpath('//a[@class="nbg"]/@title') print(results) return results re_parse(html_str) bs4_parse(html_str) lxml_parse(html_str)
4. python写爬虫的架构

从图上可以看到,整个基础爬虫架构分为5大类:爬虫调度器、URL管理器、HTML下载器、HTML解析器、数据存储器。
下面给大家依次来介绍一下这5个大类的功能:
① 爬虫调度器:主要是配合调用其他四个模块,所谓调度就是取调用其他的模板。
② URL管理器:就是负责管理URL链接的,URL链接分为已经爬取的和未爬取的,这就需要URL管理器来管理它们,同时它也为获取新URL链接提供接口。
③ HTML下载器:就是将要爬取的页面的HTML下载下来。
④ HTML解析器:就是将要爬取的数据从HTML源码中获取出来,同时也将新的URL链接发送给URL管理器以及将处理后的数据发送给数据存储器。
⑤ 数据存储器:就是将HTML下载器发送过来的数据存储到本地。
0x01 whois爬取
每年,有成百上千万的个人、企业、组织和政府机构注册域名,每个注册人都必须提供身份识别信息和联系方式,包括姓名、地址、电子邮件、联系电话、管理联系人和技术联系人一这类信息通常被叫做whois数据
import requests import re h = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36' } response = requests.get('http://whois.chinaz.com/'+input("请输入网址:"),headers=h) print(response.status_code) html = response.text #print(html) #解析数据 pattern = re.compile('class="MoreInfo".*?>(.*?)</p>',re.S) result = re.findall(pattern,html) # 方法一: # str = re.sub('\n',',',result[0]) # print(str) #方法二: print(result[0].replace('/n',','))
0x02 爬取电影信息
import requests import re import time # count = [0,10,20,30,40,50,60,70,80,90] h = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.97 Safari/537.36' } responce = requests.get('https://XX.com/board/4?offset=0', headers=h) responce.encoding = 'utf-8' html = responce.text # 解析数据 time.sleep(2) patter = re.compile('class="name">.*?title="(.*?)".*?主演:(.*?)</p>.*?上映时间:(.*?)</p>', re.S) #time.sleep(2) result = re.findall(patter, html) print(result) with open('maoyan.txt', 'a', encoding='utf-8') as f: for item in result: # 读取result(以元组的形式储存)中的内容=》 for i in item: f.write(i.strip().replace('\n', ',')) #print('\n')
0x03 爬取图片
import requests import re import time #数据的爬取img的url def get_urls(): response = requests.get('http://XX.com/png/') html_str = response.text #解析数据,得到url pattern = re.compile('<img data-original="(.*?)"') results = re.findall(pattern,html_str) print(results) return results #<img data-original="http://XX.616pic.com/ys_img/00/06/20/64dXxVfv6k.jpg"> #下载图片 def down_load_img(urls): for url in urls: response = requests.get(url) with open('temp/'+url.split('/')[-1], 'wb') as f: f.write(response.content) print(url.split('/')[-1],'已经下载成功') if __name__ == '__main__': urls = get_urls() down_load_img(urls)
0x04 线程池
线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。
"""线程池""" from concurrent.futures import ThreadPoolExecutor import time import threading def ban_zhuang(i): print(threading.current_thread().name,"**开始搬砖{}**".format(i)) time.sleep(2) print("**员工{}搬砖完成**一共搬砖:{}".format(i,12**2)) #将format里的内容输出到{} if __name__ == '__main__': #主线程 start_time = time.time() print(threading.current_thread().name,"开始搬砖") with ThreadPoolExecutor(max_workers=5) as pool: for i in range(10): p = pool.submit(ban_zhuang,i) end_time =time.time() print("一共搬砖{}秒".format(end_time-start_time))
结合多线程的爬虫:
'''美女爬取''' import requests import re from urllib.parse import urlencode import time import threading #https://www.toutiao.com/api/search/content/?aid=24&app_name=web_search&offset=0&format=json&keyword=%E7%BE%8E%E5%A5%B3&autoload=true&count=20 def get_urls(page): keys = { 'aid':'24', 'app_name':'web_search', 'offset':20*page, 'keyword':'美女', 'count':'20' } keys_word = urlencode(keys) url = 'https://www.toutiao.com/api/search/content/?'+keys_word response = requests.get(url) print(response.status_code) html_str = response.text # 解析"large_image_url":"(.*?)" pattern = re.compile('"large_image_url":"(.*?)"',re.S) urls = re.findall(pattern, html_str) return urls #下载图片 def download_imags(urls): for url in urls: try: response = requests.get(url) with open('pic/'+url.split('/')[-1]+'.jpg','wb') as f: f.write(response.content) print(url.split('/')[-1]+'.jpg',"已下载~~") except Exception as err: print('An exception happened: ') if __name__ == '__main__': start = time.time() thread = [] for page in range(3): urls = get_urls(page) #print(urls) #多线程 for url in urls: th = threading.Thread(target=download_imags,args=(url,)) #download_imags(urls) thread.append(th) for t in thread: t.start() for t in thread: t.join() end = time.time() print('耗时:',end-start)