美文网首页
支线任务-Python爬虫

支线任务-Python爬虫

作者: 长空一鱼 | 来源:发表于2019-04-30 22:48 被阅读0次

    五一小长假要到了,甄开心,肯定比写博客要开心多了,哈哈哈哈


    五一小长假快乐!

    我还在犹豫要不要写爬虫这篇,因为网上已经有大量爬虫相关资源,爬虫也不是以研究为主,而是一个获取数据的手段。

    书写目的:

    • 数据数量和质量对你运行模型的效果有着重要影响;
    • 如果数据购买昂贵又没有现成数据下载,不论个人还是公司都会首选爬虫;
    • 不需要深入爬虫知识(比如Scrapy爬虫工程),就可以获取大部分网站数据;

    装包提示:

    • 装包用pip install XXX,Baidu一下有很多指导帖
    • 学会Baidu谷歌能够让你在之后的路上走得更远更自信

    豆瓣影评

    Use Requests and regular expression

    正则表达式-重要的事情说两遍

    • [c,m,f]an: can, man, fan; [^b]og to skip bog
    • [^a-z]\w+ skip lower case begined string; \w means [A-Za-z0-9]; \d means [0-9]
    • z{3} match z three times: uzzz, wuzzzz; .{2,6} match string with length of 2-6
    • ? match ?
    • whitespace: space (␣), the tab (\t), the new line (\n) and the carriage return (\r)
    • \s will match any of the specific whitespaces above
    • \D represents any non-digit character, \S any non-whitespace character, and \W any non-alphanumeric
    • ^Mission: successful$ ^为字符串开始 and $为字符串结尾
    • ^(file_\w+) can match file_record_transcript in file_record_transcript.pdf
    • ^([A-Z]\w{2} (\d{4})) 括号中为提取的信息,此处不但提取Jan 1987,还提取1987
    • ^I love cats|I love dogs$ match "I love cats"或"I love dogs"
    • ^The.* match string starting with "The"

    正则表达式的练习在线网址: https://regexone.com/

    二话不说上代码,晕~

    import re
    import requests
    import matplotlib.pyplot as plt
    url = "https://movie.douban.com/review/best/"
    total1 = requests.get(url).text
    
    pattern1 = re.compile("https://movie.douban.com/review/\d+/")
    review_url_list = pattern1.findall(total1)
    review_url_list = list(set(review_url_list))#remove duplicates
    
    import pandas as pd
    review = []
    
    for url in review_url_list:
        total = requests.get(url).text
        pattern2 = re.compile("<p>.*</p>")
        review0 = str(pattern2.findall(total))
        review.append(review0) 
    
    DF1 = pd.DataFrame({"影评": review, "网址": review_url_list})
    DF1#可以看到影评中还有许多源码需要去除
    

    获取图片地址

    import re
    import requests
    import matplotlib.pyplot as plt
    url = "https://movie.douban.com/"
    total = requests.get(url).text
    pattern1 = re.compile("https://movie.douban.com/subject/\d+/\?from=showing")
    pattern2 = re.compile("https://img3.doubanio.com/view/photo/s_ratio_poster/public/p\d+.jpg")
    pattern2.findall(total)[:5]
    

    有了图片地址,就意味着我们可以得到图片了

    同时获取图片及命名

    Use BeautifulSoup

    import urllib.request
    import urllib
    import os
    from bs4 import BeautifulSoup
    
    import string
    table=str.maketrans({key:None for key in string.punctuation})#防止文件命名中出现标点符号,移除 ? / , .
    
    def getAllImageLink():
        for i in range(0,2):#可以设为100页或更高
            if i==0:
                url="http://www.dbmeinv.com"
            else:
                url="https://www.dbmeinv.com/?pager_offset="+str(i+1)#自己寻找翻页后网址变化规律
            html = urllib.request .urlopen(url).read()
            soup = BeautifulSoup(html)
            liResult = soup.findAll('li',attrs={"class":"span3"})
    
            for li in liResult:
                imageEntityArray = li.findAll('img')
                for image in imageEntityArray:
                    link = image.get('src')
                    imageName = image.get('title')
                    imageName=imageName.translate(table)
                    filesavepath = "%s.png" % imageName
                    urllib.request.urlretrieve(link,filesavepath)
    
    getAllImageLink()               
    
    辣么多&不正经

    伪装Header,爬取百度百科中北京地铁站

    大boss之一

    import requests
    import re
    from bs4 import BeautifulSoup
    import collections
    
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36'
    }
    
    def craw(url):
        response = requests.get(url, headers=headers)
        soup = BeautifulSoup(response.content, 'html.parser')
        return soup
    
    soup = craw('https://baike.baidu.com/item/%E5%8C%97%E4%BA%AC%E5%9C%B0%E9%93%81/408485')
    lines = soup.findAll('table')[4].findAll('a')[:-1]
    
    stations_connection = collections.defaultdict(list)
    dist = collections.defaultdict(int)
    node_in_line = collections.defaultdict(set)
    
    pattern = re.compile('([\w|\d]+)相邻站间距信息统计表')
    
    for line in lines[:-3]:
        link = 'https://baike.baidu.com' + line.get('href')
        soup = craw(link)
    
        for caption in soup.find_all('caption'):
            line_name = re.findall(pattern, caption.get_text())
            if line_name:
                print('\n----The information of {} is following...'.format(line_name[0]))
                table = caption.find_parent('table')
                for neigbor in table.find_all('tr')[1:]:
                    start, end = re.findall(re.compile('([\w|\d]+)——([\w|\d]+)'), neigbor.th.text)[0]
                    distance = re.findall(re.compile('([\d]+)米*'), neigbor.td.text)[0]
    
                    stations_connection[start].append(end)
                    stations_connection[end].append(start)
    
                    dist[(start,end)] = dist[(end,start)] = int(distance)
    
                    node_in_line[start].add(line_name[0])
                    node_in_line[end].add(line_name[0])
    
                    print('{}--{}: {}m'.format(start, end, distance))
    
                break
    

    有了这些数据,意味着你可以作出个北京地铁路线图(如图1所示)


    图1

    也意味着你可以做个北京地铁换乘的simple APP,示意如图2所示。


    图2

    手动+自动的Selenium 本章终极boss “Website Nightmare”

    既然可以手动,那就代表:

    • 你可以手动关闭弹窗
    • 手动输入账号密码跨过大部分网站门槛
    • 手动输入验证码跨过进入壁垒
    • 还一个优势就是可视化你的爬取过程
    • 虽然速度无法与Scrapy媲美,但操作性+适用性还是挺有优势的

    selenium入门教学请点击Christopher's Github

    Example: 爬取兰蔻天猫旗舰店的消费者评论

    import re
    import requests
    import time
    from bs4 import BeautifulSoup
    from selenium import webdriver
    
    url = 'https://detail.tmall.com/item.htm?spm=a1z10.3-b-s.w4011-14640892229.94.3c6f3c22ejqhZA&id=556028888955&rn=f74615e5cda8e547b07f67e1eb384119&abbucket=16&on_comment=1'
    #这里更换目标产品评论网页(天猫兰蔻旗舰店)
    driver1 = webdriver.Chrome()#谷歌自动打开之后请手动登陆
    driver1.get(url) # 打开网页
    
    import pandas as pd
    time=[0]*100
    review=[0]*100
    
    #前四页的“下一页”Xpath不一样;所以先“手动”爬前四页
    j=1#爬完一页,手动点击下一页,再j变2,变3,变4;这对于没规律的网站是很难爬,爬取大批量数据建议找有规律的网站,通过循环爬取
    for i in range(1,21):
        success =False
        while not success:
            try:
                time[(j-1)*20+i-1]=driver1.find_element_by_xpath('//*[@id="J_Reviews"]/div/div[6]/table/tbody/tr['+str(i)+']/td[1]/div[2]').text
                review[(j-1)*20+i-1]=driver1.find_element_by_xpath('//*[@id="J_Reviews"]/div/div[6]/table/tbody/tr['+str(i)+']/td[1]/div[1]/div[1]').text
                success = True
            except:
                success=True
                pass 
    
    DF1 = pd.DataFrame({"time": time, "reviews": review})
    DF1.head()#由于追加评论导致格式不一致,后期数据清洗也很重要
    

    有了消费者评论数据,你可以做

    • 评论情感打分
    • 产品属性提及率及好评率交叉分析
    • 竞品Attributes比较分析
    • Digital Marketing Strategy及市场营销策略

    Conclusion

    • 爬虫不是我们的终点与重点
    • 爬虫只是我们获取数据的一种方法
    • 运用爬虫的同时请注意法律法规
    • 通过分析数据得到我们的Insights才是重点

    Reference

    相关文章

      网友评论

          本文标题:支线任务-Python爬虫

          本文链接:https://www.haomeiwen.com/subject/jyibnqtx.html