多线程获取文章、图片、视频(m3u8)
涉及到的第三方库:requests, lxml(好像有依赖), _thread, threading等
通过requests库发送http请求,通过lxml库进行解析HTML文档,如果需要文章,就解析得到text文本然后写入txt文件即可,如果需要图片,解析到a标签的href属性,然后再发送http请求并将请求得到的内容直接写入jpg文件即可,如果需要视频,会相对麻烦一点,参考。
requests
比较常用的是该模块的get, post方法,必要参数为url,常用参数有headers, cookies, timeout, data, json, files。
- url:请求的目标
- headers:请求头。常用的有:
User-Agent,Content-Type,x-requested-with, 也可以将cookie字符串放在这里 - cookies: 略(可以通过
requests.cookies.RequestsCookieJar()进行填充k,v) - timeout: 连接超时、读取超时时间(不设置的话,可能会造成程序阻塞:请求发送后不响应也不抛异常)。也可以通过
requests.adapters.DEFAULT_RETRIES = 3设置阻塞后的自动重试次数 - data, json, files:请求携带的参数、内容
也可以使用requests.session来保持会话状态:
import requests
s = requests.session()
# 也可以分别设置连接(5)、读取超时(3):timeout=(5, 3)
res = s.get(url, headers={'User-Agent': ua}, timeout=3)
返回结果是一个response对象(res),res.status_code是响应码,res.content是二进制内容(图片),res.text是经过编码后的文本(HTML文档,使用lxml解析),异步请求可以通过res.json()得到请求结果。
lxml
import requests
import lxml.html
# 发送get请求,获取响应
res = requests.get(url, timeout=(3,3))
# 使用lxml.html解析返回的html文档
source = lxml.html.fromstring(res.text)
# 获取解析后的id以 nav-chapter 开头的所有节点下的所有a节点(返回的是 list<node>)
node = source.xpath('//*[starts-with(@id, "nav-chapter")]/a')
# 获取class="main-text-wrap" 的div下的第二个div下的text(返回的是 list<str>)
txts = source.xpath('//div[@class="main-text-wrap"]/div[2]/text()')
# 获取 id="j_chapterNext" 的a节点的href属性(超链接)(返回的是 list<str>)
hrefs = source.xpath('//a[@id="j_chapterNext"]/@href')
更多xpath语法,详见 xpath
thread
有两种方式,一种是直接另开一个线程运行给定的function,后面一个元组,放这个函数的参数。另一种是通过实现Thread类的run方法,然后调用start方法启动线程。
方式一
import _thread
def test(name, interval):
for i in range(10):
print('%s : %6d' % (name, i))
time.sleep(interval)
th_1 = _thread.start_new_thread(test, ('th-a', 0.1, ))
th_2 = _thread.start_new_thread(test, ('th-b', 0.2, ))
方式二
from threading import Thread, Lock
class MyThread(Thread):
def __init__(self, name, lock, data):
Thread.__init__(self)
self.name = name
self.lock = lock
self.data = data
# 多线程需要调用的方法
def run(self):
for i in range(10):
# 获取锁
self.lock.acquire()
tmp = self.data['cur']
self.data['cur']+=1
# 释放锁
self.lock.release()
print('%-6d %s cur: %6d' % (i, self.name, tmp))
self.data[self.name+str(i)] = tmp
time.sleep(0.1)
print('%s end!' % self.name)
lock = Lock()
data = {'cur': 0}
th_1 = MyThread('Th-a', lock, data)
th_2 = MyThread('Th-b', lock, data)
# 开启线程
th_1.start()
th_2.start()
# 使主线程等待至 1、2线程终止
th_1.join()
th_2.join()
# 打印data
print(data)
更多 python 多线程