python多线程爬虫简记(无完整代码)

248 阅读2分钟

多线程获取文章、图片、视频(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 多线程