多线程爬取药品信息
利用多线程来获取药品信息可以实现高效的爬取,方便我们自己对药品的名称、价格以及功效进行了解和掌握
导入需要使用到的包
python">from concurrent.futures.thread import ThreadPoolExecutor
from lxml import etree
import requests
import random
import csv
目标网站
39药品通
这个网站提供的药品信息非常全,本身网站做的也很简洁明了,标签规整,非常适合信息爬取
以皮肤用药为例,我们可以利用xpath定位来定位我们想要获取到的元素
分别是名称,适用症状以及药品参考价格
知道这些信息之后开始写代码
- 首先我们利用文件管理以及csv的writer构造我们要使用的写入文件对象
python">fp = open('../dataset/druginfo.csv', 'a+', encoding='utf-8', newline='')
writer = csv.writer(fp)
- 之后再构造headers和代理池(如果有购买就用你购买的)防止ip封锁反爬
python">headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1660.57",
}
proxies_pool = [
{'http': '114.231.109.88:8088'},
{'http': '114.231.42.23:8808'},
{'http': '113.223.215.204:8080'},
{'http': '117.69.136.23:8009'},
]
- 接着定义一个download函数用来接收我们传入的url并对数据进行解析和下载
python">def download(url):
proxies = random.choice(proxies_pool)
response = requests.get(url=url, headers=headers, proxies=proxies)
content = response.text
tree = etree.HTML(content) # IMPORTANT:调用etree解析页面源码
namelst = tree.xpath('//div[@class="drugs-brief"]/p/a/@title') # TIPS:获取药品名称
efficacylst = tree.xpath('//div[@class="drugs-brief"]/p[2]/text()') # TIPS:药品功效概述
pricelst = tree.xpath('//div[@class="drugs-brief"]/p[4]/span/text()') # TIPS:药品价格
for i in range(len(namelst)):
name = namelst[i].strip()
efficacy = efficacylst[i].strip()
try:
price = pricelst[i].strip()
except IndexError:
price = ' '
infolst = [name, efficacy, price]
# tips:当然这里还可以用拼接字符串的写法
print(infolst)
writer.writerow(infolst)
注意上面代码写了一处异常处理,因为爬取的时候报错了,然后我发现后面有些页面的药品是没有标注价格的!!!
- 接下来构造主函数
python">if __name__ == '__main__':
with ThreadPoolExecutor(10) as t: # important:开启大小为20的线程池
for j in range(1, 80):
url = f'https://ypk.39.net/pifu/p{j}/'
t.submit(download, url)
由于皮肤用药大概有88页,所以在主函数中设置到80页看看效果
注意:
- 我们在主函数中开启了线程池,大小指定为10,构造循环遍历页码然后利用.submit将url作为参数传入到我们写的download函数中去让它来处理传入的url,对其进行解析并获取我们要爬取的信息,然后写入到csv文件当中
运行结果
获取了1200多条数据,而且因为开启了多线程,运行速度很快
如果本文对你使用多线程爬取有帮助,请点赞收藏,您的鼓励是我创作的动力