前阵子看了篇文章,做百度相关搜索的循环爬取用于抓需求。
方法是爬取百度相关搜索结果,然后通过判断同页面的百度搜索结果的域名和我的域名库的交集是否大于2,从而判断这个相关搜索是不是我所需要的。
然后循环爬取,可以积累大量同领域相关的问题。
没学过编程,自学了一周,把这个代码手撸了出来,水平有限,代码逻辑写的乱,欢迎各位大佬修改拍砖。
[Asm] 纯文本查看 复制代码 import threading
from concurrent.futures import ThreadPoolExecutor
import requests
from lxml import etree
import queue
import urllib
from urllib import parse
import urllib.request
from urllib.parse import urlparse
import json
lock = threading.Lock()
proxies = {
}
# cookie自己抓
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
'Cookie': ''
}
# 1:循环提取队列关键词到百度搜索,提取结果页面的链接和标题。
def get_domain(url):#获得主域名
domain =urlparse(url).hostname
return domain
def get_url(baidu_url):#转换为原始url
header = requests.head(baidu_url).headers
url = header.get('location')
return url
def get_new_key(tree): #返回新的关键词列表
new_key = tree.xpath('//*[@id="rs_new"]/table/tbody/tr/td/a/@title')
return new_key
def get_web_data(tree): #获得页面数据列表
all_webdata = tree.xpath('//h3/a')
web_data = []
for it in all_webdata:
x = it.xpath('string(.)')
web_data.append(x)
return web_data
# 2:将提取出的百度链接批量转化为原始URL,提取所有原始URL的主域名与行业域名库比对(转化为set集合取交集)。
def get_result(key): #获得最终关键词
search_link = 'https://www.baidu.com/s?ie=utf-8&wd=%s&pn=20' % urllib.parse.quote(key)
resp = requests.get(search_link,headers = headers,proxies=proxies)
html= resp.text
tree = etree.HTML(html)
baidu_url = tree.xpath('//*[@id="content_left"]/div')
with lock:
ls = set() #不要的字典
for it in baidu_url:
try:
bd_url = it.xpath('h3/a/@href')[0]
except IndexError:
continue
url = get_url(bd_url)
domain = get_domain(url)
ls.add(domain)
# 根据设置的阈值(一般设置25%左右,10个链接2-3个命中即可,没有固定标准)判断是否为目标领域词,根据得到的判定选择是否提取和保存”相关搜索”词。
if len(ls&need_url)>2:
new_key = get_new_key(tree)
web_data = get_web_data(tree)
print(f"抓取关键词【{key}】:完成")
return new_key,web_data
else:
outcast_key.add(key)
print(f"抓取关键词【{key}】:异类")
if __name__ == '__main__':
main_key = ['育儿']
seen_key = set(main_key)
# 所需数据
key_web_data = dict()
outcast_key = set()
# 所需url的字典
f = open('needurl.txt', 'r+',encoding='UTF-8')
need_url = {'www.baidu.com'}
txt = f.readlines()
for it in txt:
need_url.add(it.strip())
print('任务开始!请不要随意关闭!')
# 设置队列
queue_key = queue.Queue()
pool = ThreadPoolExecutor(50) # 多线程
# 关键词放入队列中
for key in seen_key: # 当关键词在seen_key里
queue_key.put(key) #把seen_key的关键词加入到队列中
while queue_key.empty() == False:
key = queue_key.get() #从队列获取关键词
if key in key_web_data: continue #当关键词在已储存数据里,跳过
if key in outcast_key:continue #当关键词在不要的关键词里,跳过
try:
# new_key,web_data = get_result(key) #单线程
new_key, web_data = pool.submit(get_result,key).result()
for nk in new_key:
if nk in seen_key: continue
seen_key.add(nk)
queue_key.put(nk)
key_web_data[key] = web_data
if len(key_web_data) >= 2000:
print('爬取完成')
break
# 保存成json
json_str = json.dumps(key_web_data, indent=4)
with open(f'{main_key[0]}data.json', 'a+') as json_file:
json_file.write(json_str)
json_file.flush()
# 保存成txt
with open(f'{main_key[0]}关键词.txt', 'a+', encoding='UTF-8') as datatxt:
datatxt.write(key + '\n')
datatxt.flush()
except TypeError:
continue |