功能篇之爬虫
#基于cookie的案例分析:https://xueqiu.com/ import requests from lxml import etree import requests headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36' } #自动获取cookie,cookie就会自动存储到session中 session = requests.Session() session.get('https://xueqiu.com/',headers=headers) #捕获ajax数据包获取的url url = 'https://xueqiu.com/v4/statuses/public_timeline_by_category.json?since_id=-1&max_id=-1&count=10&category=-1' #携带cookie进行的请求发送 dic_json = session.get(url=url,headers=headers).json() print(dic_json)
爬虫中正则的使用
def detail_parse(self, response): news_text=response.text content_list=re.findall('"digest":"(.*?)"',news_text)
detail_page_text = requests.get(url=detail_url,headers=headers).text video_url = re.findall(ex,detail_page_text,re.S)[0]
for k,div in enumerate(div_list): title=re.findall('<a class=\"title_wl\".*?>(.*?)</a>',page_text)[k]
爬虫中xpath的使用
1.下载:pip install lxml 2.导包:from lxml import etree 3.将html文档或者xml文档转换成一个etree对象,然后调用对象中的方法查找指定的节点 2.1 本地文件:tree = etree.parse(文件名) tree.xpath("xpath表达式") 2.2 网络数据:tree = etree.HTML(网页内容字符串) tree.xpath("xpath表达式")
4.注意xpath匹配的对象均以列表的形式返回
def title_parse(self, response): detailnews_div_list = response.xpath('//div[@class="ndi_main"]/div') for detailnews_div in detailnews_div_list[0:2]: title = detailnews_div.xpath('./div/div[1]/h3/a//text()').extract_first() detailnews_url = detailnews_div.xpath('./div/div[1]/h3/a//@href').extract_first() item = WangyinewsallItem() item['title'] = title yield scrapy.Request(url=detailnews_url, callback=self.detail_parse, meta={'item': item})
new_detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()
li_list = response.xpath('//div[@class="ns_area list"]/ul/li')
VIEWSTATE_value=tree.xpath('//*[@id=\"__VIEWSTATE\"]/@value')[0]
from lxml import etree page_text = requests.get(url=url,headers=headers,proxies={'http':'116.228.233.90:8082'}).text tree = etree.HTML(page_text) code_img_url = tree.xpath('//*[@id=\"verifyPic_login\"]/@src')[0]
爬虫中beautifulsoop的使用
#安装环境 pip install bs4 pip install lxml #导入beautiful包 from bs4 import BeautifulSoup #实例化一个BeautifulSoup对象 #本地加载: soup=BeautifulSoup(fp,'lxml') #网络加载: soup=BeautifulSoup(page_text,'lxml'),其中page_text为响应对象 基础巩固: (1)根据标签名查找 - soup.a 只能找到第一个符合要求的标签 (2)获取属性 - soup.a.attrs 获取a所有的属性和属性值,返回一个字典 - soup.a.attrs['href'] 获取href属性 - soup.a['href'] 也可简写为这种形式 (3)获取内容 - soup.a.string - soup.a.text - soup.a.get_text() 【注意】如果标签还有标签,那么string获取到的结果为None,而其它两个,可以获取文本内容 (4)find:找到第一个符合要求的标签 - soup.find('a') 找到第一个符合要求的 - soup.find('a', title="xxx") - soup.find('a', class_="xxx") - soup.find('a', id="xxx") (5)find_all:找到所有符合要求的标签 - soup.find_all('a') - soup.find_all(['a','b']) 找到所有的a和b标签 - soup.find_all('a', limit=2) 限制前两个 (6)根据选择器选择指定的内容 select:soup.select('#feng') - 常见的选择器:标签选择器(a)、类选择器(.)、id选择器(#)、层级选择器 - 层级选择器: div .dudu #lala .meme .xixi 下面好多级 div > p > a > .lala 只能是下面一级 【注意】select选择器返回永远是列表,需要通过下标提取指定的对象
#爬取斗破苍穹网站的小说 import requests import re import json import os import time from bs4 import BeautifulSoup url="https://doupocangqiong1.com/486/37zw/list_1.html" headers={ "User-Agent":"Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36" } page_text=requests.get(url=url,headers=headers).text soup=BeautifulSoup(page_text,'lxml') span_list=soup.find_all('span',class_='n') with open('神道丹尊.txt','wt',encoding='utf-8')as f: for span in span_list[0:1]: title=' '.join(span.a.string.split(' ')[1:]) data_list=span.a['href'].split('/') cid=re.search('\d+',data_list[2]).group() data={ "siteid":'69', "bid":data_list[1], "cid":cid } noval_url="https://doupocangqiong1.com/novelsearch/chapter/transcode.html" json_content=requests.post(url=noval_url,headers=headers,data=data).content init_content=json.loads(json_content).get('info','') content=init_content.replace('<br>\n<br>','') f.write(title+'\n\n') f.write(content)
soup.p.text soup.p.string soup.p.get_text() soup.find_all('div') soup.find('div',class_=\"song\").get_text() soup.select('.song') soup.select('.tang > ul > li')
标签定位: soup.标签名称:定位标签;如有多个,返回第一个符合的标签。 soup.find(tagname,attrName="value"):基于属性定位实现的标签定位,语法格式'div',class_='song',关键字(只有class??)需要下划线,返回单个标签 soup.find_all(tagname,attrName="value")返回列表 取数据: 取文本 soup.tagname.text 取得标签下所有的标签内容 soup.tagname.get_text 取得标签下所有的标签内容 soup.tagname.string 取得标签中直系的文本内容 取属性 soup.tagname['attrName'] select:使用选择器定位标签 标签,类,id选择器:soup.select('.song')返回列表 层级选择器: 单层级: soup.select('.song>ul>li') 多层级: soup.select('.song li')
- event_loop:事件循环,相当于一个无限循环,我们可以把一些函数注册到这个事件循环上,当满足某些条件的时候,函数就会被循环执行。程序是按照设定的顺序从头执行到尾,运行的次数也是完全按照设定。当在编写异步程序时,必然其中有部分程序的运行耗时是比较久的,需要先让出当前程序的控制权,让其在背后运行,让另一部分的程序先运行起来。当背后运行的程序完成后,也需要及时通知主程序已经完成任务可以进行下一步操作,但这个过程所需的时间是不确定的,需要主程序不断的监听状态,一旦收到了任务完成的消息,就开始进行下一步。loop就是这个持续不断的监视器。
- coroutine:中文翻译叫协程,在 Python 中常指代为协程对象类型,我们可以将协程对象注册到事件循环中,它会被事件循环调用。我们可以使用 async 关键字来定义一个方法,这个方法在调用时不会立即被执行,而是返回一个协程对象。
- task:任务,它是对协程对象的进一步封装,包含了任务的各个状态。
- future:代表将来执行或还没有执行的任务,实际上和 task 没有本质区别。
- 另外我们还需要了解 async/await 关键字,它是从 Python 3.5 才出现的,专门用于定义协程。其中,async 定义一个协程,await 用来挂起阻塞方法的执行。
import aiohttp import asyncio #回调函数:解析响应数据 def callback(task): print('this is callback()') #获取响应数据 page_text = task.result() print('在回调函数中,实现数据解析') async def get_page(url): async with aiohttp.ClientSession() as session: async with await session.get(url=url) as response: page_text = await response.text() #read() json() # print(page_text) return page_text start = time.time() urls = [ 'http://127.0.0.1:5000/bobo', 'http://127.0.0.1:5000/jay', 'http://127.0.0.1:5000/tom', ] tasks = [] loop = asyncio.get_event_loop() for url in urls: c = get_page(url) task = asyncio.ensure_future(c) #给任务对象绑定回调函数用于解析响应数据 task.add_done_callback(callback) tasks.append(task) loop.run_until_complete(asyncio.wait(tasks)) print('总耗时:',time.time()-start)
1.encoding='utf-8'
response=requests.get(url=url,headers=headers) response.encoding='utf-8' page_text=response.text
2.使用更广的编码集
#示例1: img_name = li.xpath('./a/b/text()')[0] img_name = img_name.encode('iso-8859-1').decode('gbk') #示例2: title=t.encode('iso-8859-1').decode('GBK')