LangChain实战课-21-部署一个鲜花网络电商的人脉工具(上) | 豆包MarsCode AI刷题

125 阅读3分钟

需求

为了推广鲜花网络电商,利用微博上的大V做宣传。找到微博上适合做鲜花推广的大V,并给出具体的联络方案。

项目实现细节

第一步:  通过LangChain的搜索工具,以模糊搜索的方式,帮助运营人员找到微博中有可能对相关鲜花推广感兴趣的大V(比如喜欢玫瑰花的大V),并返回UID。

第二步:  根据微博UID,通过爬虫工具拿到相关大V的微博公开信息,并以JSON格式返回大V的数据。

第三步:  通过LangChain调用LLM,通过LLM的总结整理以及生成功能,根据大V的个人信息,写一篇热情洋溢的介绍型文章,谋求与该大V的合作。

第四步:  把LangChain输出解析功能加入进来,让LLM生成可以嵌入提示模板的格式化数据结构。

第五步:  添加HTML、CSS,并用Flask创建一个App,在网络上部署及发布这个鲜花电商人脉工具,供市场营销部门的人员使用。

前两步的实现

第一步 找到大V

  1. 设计主程序
if __name__ == '__main__':
    response_UID = lookup_V(flower_type='玫瑰')
    UID = re.findall(r'\d+', response_UID)[0]
  1. 实现lookup_V
def lookup_V(flower_type: str):
    llm = ChatOpenAI(temperature=0, model='gpt-3.5-turbo')
    
    template = """
    Given the {flower} I want you to get a related WeiBo UID.Your answer should only contain UID.The URL always starts with https://weibo.com/u for example, if https://weibo.com/u/1669879400 is her 微博, then 1669879400 is her UID.This is only the example don't give me this, but the actual UID.
    """
    
    prompt_template = PromptTemplate(input_variables=["flower"], template=template)
    
    tools = [
        Tool(
            name="Craw Google for WeiBo page",
            func=get_UID,
            description="useful when you need get the WeiBo UID"
        )
   ]
       
    agent = initialize_agent(
        tools, 
        llm, 
        agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,
        verbose=True
    )
    
    ID = agent.run(prompt_template.format_prompt(flower=flower_type))
    
    return ID
  1. 实现工具get_UID
def get_UID(flower: str):
    search = SerpAPIWrapper()
    res = search.run(flower)
    return res

按理说到现在为止其实代码就完成了第一部分的功能了,但是实际运行下来发现并未正确提取出我们需要的UID,经过排查发现是serpAPIWrapper它返回的搜索是文本内容,并没有直接返回对应的link,因此我们需要针对源码做一些调整,方式是通过继承去修改

class CustomSerpAPIWrapper(SerpAPIWrapper):    
    def __init__(self):         
        super(CustomSerpAPIWrapper, self).__init__()
    ....
    ....
    if "organic_results" in res.keys():             
        first_organic_result = res["organic_results"][0]             
    if "snippet" in first_organic_result.keys():                 
        # snippets.append(first_organic_result["snippet"]
        snippets.append(first_organic_result["link"])
    ....
    ....
    
def get_UID(flower: str):
    """Searches for Linkedin or twitter Profile Page."""
    # search = SerpAPIWrapper()
    search = CustomSerpAPIWrapper()
    res = search.run(f"{flower}")
    return res

image.png

第二步 爬取大V资料

  1. 扩充主程序
person_info = get_data(UID)
  1. 实现get_data
def get_data(id):
    url = "https://weibo.com/ajax/profile/detail?uid={}".format(id)
    html = scrape_weibo(url)
    response = json.loads(html)
    return response
  1. 实现scrape_weibo(url: str):
# 定义爬取微博用户信息的函数
def scrape_weibo(url: str):
    '''爬取相关鲜花服务商的资料'''
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36",
        "Referer": "https://weibo.com"
    }
    cookies = {
        "cookie": '''SINAGLOBAL=3762226753815.13.1696496172299; ALF=1699182321; SCF=AiOo8xtPwGonZcAbYyHXZbz9ixm97mWi0vHt_VvuOKB-u4-rcvlGtWCrE6MfMucpxiOy5bYpkIFNWTj7nYGcyp4.; _sc_token=v'''
    }
    response = requests.get(url, headers=headers, cookies=cookies)
    time.sleep(3)   # 加上3s 的延时防止被反爬
    return response.text
  1. 精简输出

将得到的结果信息结果进行一个精简(为了节省token)

import re

def contains_chinese(s):
    return bool(re.search('[\u4e00-\u9fa5]', s))

def remove_non_chinese_fields(d):
    if isinstance(d, dict):
        to_remove = [key for key, value in d.items() if isinstance(value, (str, int, float, bool)) and (not contains_chinese(str(value)))]
        for key in to_remove:
            del d[key]
        
        for key, value in d.items():
            if isinstance(value, (dict, list)):
                remove_non_chinese_fields(value)
    elif isinstance(d, list):
        to_remove_indices = []
        for i, item in enumerate(d):
            if isinstance(item, (str, int, float, bool)) and (not contains_chinese(str(item))):
                to_remove_indices.append(i)
            else:
                remove_non_chinese_fields(item)
        
        for index in reversed(to_remove_indices):
            d.pop(index)