2024年Python最全一个价值一千五的外包项目!抓取大众点评的店铺信息!(1),2024年最新吊打面试官 敖丙

如果你也是看准了Python,想自学Python,在这里为大家准备了丰厚的免费学习大礼包,带大家一起学习,给大家剖析Python兼职、就业行情前景的这些事儿。

一、Python所有方向的学习路线

Python所有方向路线就是把Python常用的技术点做整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照上面的知识点去找对应的学习资源,保证自己学得较为全面。

二、学习软件

工欲善其必先利其器。学习Python常用的开发软件都在这里了,给大家节省了很多时间。

三、全套PDF电子书

书籍的好处就在于权威和体系健全,刚开始学习的时候你可以只看视频或者听某个人讲课,但等你学完之后,你觉得你掌握了,这时候建议还是得去看一下书籍,看权威技术书籍也是每个程序员必经之路。

四、入门学习视频

我们在看视频学习的时候,不能光动眼动脑不动手,比较科学的学习方法是在理解之后运用它们,这时候练手项目就很适合了。

四、实战案例

光学理论是没用的,要学会跟着一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

五、面试资料

我们学习Python必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有阿里大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。

成为一个Python程序员专家或许需要花费数年时间,但是打下坚实的基础只要几周就可以,如果你按照我提供的学习路线以及资料有意识地去实践,你就有很大可能成功!
最后祝你好运!!!

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化学习资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

def getData(baseURL):

for i in range(1,10):

URL = baseURL + str(i)

html = askURL(URL)#html是askURL的返回结果,循环下的html记录单页的爬取结果,因此数据解析提取也需要在循环内进行

使用开发者工具读取源码,可以看到全部的店铺信息储存在ID为shop-list-all-list的div标签中,每个li标签为一条店铺记录。其中pic分类记录缩略图、txt分类记录店铺信息,svr-info记录团购信息

2.2 使用BeautifulSoup


方案1:提取多个标签,手动合并

soup = BeautifulSoup(html, “html.parser”)

soupfind = soup.find_all(‘div’, { ‘class’ :{“pic” , “txt” , “svr-info”}})#提取多个标签下信息时的处理方式,会提取为3个列表,需要手动合并为一个

#仅提取单个标签时的写法

soupfind = soup.find_all(‘div’, class_ :“txt” )

#合并过程(仅供参考)

soup_find = []

i = 0

while i < len(soupfind):

l = “”

l = str(soupfind[i]) + str(soupfind[i+1]) + str(soupfind[i+2])

soup_find.append(l)

i += 3

但后续操作中发现,部分店铺不含团购信息,导致”svr-info“class下面为空值,每三个合并出现错误

方案2:由于每个店铺的全部信息含在一个

  • 标签下
  • def getData(baseURL):

    for i in range(1, 11):

    URL = baseURL + str(i)

    html = askURL(URL)

    soup = BeautifulSoup(html, “html.parser”)

    soup_find = soup.find_all(‘li’, class_ = “”)

    但这种方式会提取出一些非店铺的分支,会造成正则表达式搜索结构出现大量空值,带来混乱,关注到title与店铺信息间必然存在一一对应关系,后续将采用这一方法剔除非店铺分支。

    2.3 正则表达式


    全部信息的正则表达式提取如下:

    for item in soup_find:

    item = str(item)

    imgsrc = re.findall(re.compile(r’data-src=“http(.*?)😕/(.*?).meituan.net/(.*?)”'), item) # 图片

    title = re.findall(re.compile(r’

    (.*?)
    '), item) # 店名

    if title == []: #

  • 标签会筛选出一些非店铺的分支,由于title是店铺信息一定含有的信息,使用title筛选,留下店铺信息
  • pass

    else:

    if imgsrc == []:

    img = []

    else:

    img = [“http” + (imgsrc[0])[0] + “😕/” + (imgsrc[0])[1] + “.meituan.net/” + (imgsrc[0])[2]]

    branch = re.findall(re.compile(r’分店’), item) # 分店

    if branch == “分店”:

    ifbranch = [“1”]

    else:

    ifbranch = [“0”]

    if re.findall(re.compile(r’

    (.*?)
    '), item) == []:

    star = []

    score = []

    else:

    star = (re.findall(re.compile(r’

    (.*?)
    '), item)[0])[

    0] # 星级

    score = (re.findall(re.compile(r’

    (.*?)
    '), item)[0])[

    1] # 评分

    numraters = re.findall(re.compile(r’(.*?)\s*条评价'), item) # 评分人数

    avgprice = re.findall(re.compile(r’人均\s*¥(.*?)'), item) # 人均价格

    taste = re.findall(re.compile(r’口味(.*?)'), item) # 口味

    enviro = re.findall(re.compile(r’环境(.*?)'), item) # 环境

    serv = re.findall(re.compile(r’服务(.*?)'), item) # 服务

    variety = re.findall(

    re.compile(r’<a data-click-name=“shop_tag_cate_click”.*?">(.*?)'),

    item) # 菜品种类

    zone = re.findall(

    re.compile(r’<a data-click-name=“shop_tag_region_click”.*?">(.*?)'),

    item) # 地址分区

    address = re.findall(re.compile(r’(.*?)\s*'), item) # 详细地址

    recommend = re.findall(re.compile(

    r’<a class=“recommend-click” data-click-name=“shop_tag_dish_click”.*?target=“_blank”>(.*?)'),

    item) # 推荐菜

    tg_info = re.findall(re.compile(

    r’\s*团购:(.*?)\s*'),

    item) # 团购信息

    coupon = re.findall(re.compile(r’优惠:(.*?)\s*'), item) # 优惠信息

    data = []

    data.append(img)

    data.append(title)

    data.append(ifbranch)

    data.append(star)

    data.append(score)

    data.append(numraters)

    data.append(avgprice)

    data.append(taste)

    data.append(enviro)

    data.append(serv)

    data.append(variety)

    data.append(zone)

    data.append(address)

    data.append(recommend)

    data.append(tg_info)

    data.append(coupon)

    datalist.append(data)

    提取结果:

    [[‘http://p0.meituan.net/biztone/193986969_1624004529519.jpeg%40340w_255h_1e_1c_1l%7Cwatermark%3D0’], [‘桂满陇-锦绣江南(万象城店)’], [0], ‘45’, ‘4.66’, [‘\uec0e\ue10c1\uf819’], [‘\uec0e\ue498’], [‘\ue82c.\uf819\ue3b9’], [‘\ue82c.\uecd2\ue82c’], [‘\ue82c.\ue3b9\uf819’], [‘浙\ue913’], [‘\uf35e\ue12a\ueac9’], [‘吴\uf136\uf36b1599\uf75f\uea4c象\uf7d04\uf370402A\uf089\ue668’], [‘吮指鸡爪’, ‘石锅沃豆腐’, ‘公主素蟹粉’], [‘桂满陇·西湖船宴!仅售388元!价值454元的招牌必尝四人餐1份,提供免费WiFi。’], []

    3. 字体反爬


    3.1 字体反爬方式


    上图爬出的数据中有较多

    \uec0e\ue10c1\uf819

    类型的乱码。这是因为大众点评采用Web字体反爬的方式。

    ”即通过创建自定义字体,改变部分常用字符的Unicode编码。由于服务器端记录了新字体与Unicode编码之间的映射关系,网页端能够识别改变了Unicode编码后的字符并正常显示。然而,当爬虫直接爬取HTML源码并访问子标签值时,由于本地没有对应的字体文件,就无法正常解析Unicode编码,从而显示为方框。“(来源:https://www.cnblogs.com/weosuper/p/13954662.html)

    以评价为例,直接爬取的信息会是乱码的形式,因此需要进一步对爬取数据进行解码。

    3.2 获取网页字体库


    以shopNum字体为例,提取css文件,地址

    http://s3plus.meituan.net/v1/mss_0a06a471f9514fc79c981b5466f56b91/svgtextcss/3a1fbc361fa4c6a862e661e34778709f.css

    可以看到网页共定义了4种字体:PingFangSC-Regular-shopNum;PingFangSC-Regular-tagName;PingFangSC-Regular-address;PingFangSC-Regular-reviewTag。(进一步分析可发现字体文件名两两一致,即网页端实际上使用了两种字体,这会为之后的解码减轻一定工作量)

    搜索找到该URL在HTML源码中的位置

    进一步缩小范围,发现svgtextcss可以唯一对应该字段。据此,使用正则表达式提取地址,访问css文件,在解码后的文件中再次使用正则表达式解析得到woff字体文件存储。此段代码如下:

    def getWoff(baseURL):

    url = baseURL + “1”

    html = askURL(url)

    print(html)

    css_str = re.findall(re.compile(r’href=“(.*?)svgtextcss(.*?).css”>'), html)

    css_url = “http:” + css_str[0][0] + “svgtextcss” +css_str[0][1] + “.css”

    html_css = str(urllib.request.urlopen(urllib.request.Request(css_url)).read())

    #没有登陆、反爬操作,可以不加header直接读取源码

    #urllib.request返回的是byte类型

    woff_url = re.findall(re.compile(r’//s3plus.meituan.net/v1/mss_\w{32}/font/\w{8}.woff’),html_css)

    print(woff_url)

    tags = [‘shopNum’,‘tagName’,‘address’,‘reviewTag’]

    woff_files = []

    for nNum, url in enumerate(woff_url):

    res_woff = urllib.request.urlopen(urllib.request.Request(“http:” + url)) #返回类别:HTTPResponce

    print(res_woff)

    with open(‘./woff/’ + tags[nNum] + ‘.woff’,“wb”) as f:#需要在py文件路径下新建woff文件夹

    f.write(res_woff.read()) #读取文件

    woff_files.append(‘./woff/’ + tags[nNum] + ‘.woff’)

    return(dict(zip(tags, woff_files)))

    之后将在新建的woff文件夹中生成4个字体文件:

    使用fontcreator打开woff包,可看到字体反爬中加密的字体:

    3.3 建立新的映射


    建立两个新的映射:shopNum和tagName。其中address与shopNum映射方式一致,tagName与reviewTag映射方式一致。

    shopNum的映射方式建立如下所示:

    shopNum = TTFont(‘./woff/shopNum.woff’)

    woff_unicode = shopNum[‘cmap’].tables[0].ttFont.getGlyphOrder()

    woff_glpy_shopNum = []

    for i in woff_unicode:

    woff_glpy_shopNum.append(i.replace(“uni”, “u”))

    woff_str_601 = ‘1234567890店中美家馆小车大市公酒行国品发电金心业商司超生装园场食有新限天面工服海华水房饰城乐汽香部利子老艺花专东肉菜学福饭人百餐茶务通味所山区门药银农龙停尚安广鑫一容动南具源兴鲜记时机烤文康信果阳理锅宝达地儿衣特产西批坊州牛佳化五米修爱北养卖建材三会鸡室红站德王光名丽油院堂烧江社合星货型村自科快便日民营和活童明器烟育宾精屋经居庄石顺林尔县手厅销用好客火雅盛体旅之鞋辣作粉包楼校鱼平彩上吧保永万物教吃设医正造丰健点汤网庆技斯洗料配汇木缘加麻联卫川泰色世方寓风幼羊烫来高厂兰阿贝皮全女拉成云维贸道术运都口博河瑞宏京际路祥青镇厨培力惠连马鸿钢训影甲助窗布富牌头四多妆吉苑沙恒隆春干饼氏里二管诚制售嘉长轩杂副清计黄讯太鸭号街交与叉附近层旁对巷栋环省桥湖段乡厦府铺内侧元购前幢滨处向座下臬凤港开关景泉塘放昌线湾政步宁解白田町溪十八古双胜本单同九迎第台玉锦底后七斜期武岭松角纪朝峰六振珠局岗洲横边济井办汉代临弄团外塔杨铁浦字年岛陵原梅进荣友虹央桂沿事津凯莲丁秀柳集紫旗张谷的是不了很还个也这我就在以可到错没去过感次要比觉看得说常真们但最喜哈么别位能较境非为欢然他挺着价那意种想出员两推做排实分间甜度起满给热完格荐喝等其再几只现朋候样直而买于般豆量选奶打每评少算又因情找些份置适什蛋师气你姐棒试总定啊足级整带虾如态且尝主话强当更板知己无酸让入啦式笑赞片酱差像提队走嫩才刚午接重串回晚微周值费性桌拍跟块调糕’

    #这里601个字符的提取方式为:使用OCR软件识别fontcreator中显示的字形,按顺序转换为字符串。此处工作较为繁琐,但目前没有找到比较合适的其他办法

    woff_character = [‘.notdef’, ‘x’] + list(woff_str_601)

    woff_dict_shopNum = dict(zip(woff_glpy_shopNum, woff_character))

    将datalist中的代码转译为字符。

    def woff1(num):

    num1 = (repr(num).replace(“'”, “”).replace(“[”, “”).replace(“]”, “”).replace(“\\”,“”)).split(“”)

    #repr(str):相当于r’,否则转义字符生效,“'”,"\"无法被替换

    t = 0

    while t < len(num1):

    if num1[t][-5:] in woff_dict_shopNum.keys():

    #由于并非所有的字符都被加密,会出现”未加密字符+加密字符“的结构。观察发现加密字符长度为5位,这里提取后5位,并将组合结构拆开。

    num1.insert(t,num1[t][:-5])

    num1[t+1] = woff_dict_shopNum[num1[t+1][-5:]]

    elif num1[t][-6:-1] in woff_dict_shopNum.keys():

    num1.insert(t,num1[t][-1:])

    num1[t+1] = woff_dict_shopNum[num1[t+1][-6:-1]]

    elif num1[t][-7:-2] in woff_dict_shopNum.keys():

    num1.insert(t,num1[t][-2:])

    num1[t+1] = woff_dict_shopNum[num1[t+1][-7:-2]]

    #防止后接数字/字符的情况

    t = t + 1

    return(num1)

    def getshopNum(datalist):

    for i in datalist:

    for j in range (5,10):

    num = i[j][0].replace(‘’,“”).replace(“”,“”)

    num1 = woff1(num)

    i.pop(j)

    i.insert(j,num1)

    return(datalist)

    4. 存储到excel表格中


    简单套用代码即可,不再赘述。

    现在能在网上找到很多很多的学习资源,有免费的也有收费的,当我拿到1套比较全的学习资源之前,我并没着急去看第1节,我而是去审视这套资源是否值得学习,有时候也会去问一些学长的意见,如果可以之后,我会对这套学习资源做1个学习计划,我的学习计划主要包括规划图和学习进度表。

    分享给大家这份我薅到的免费视频资料,质量还不错,大家可以跟着学习

    网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

    需要这份系统化学习资料的朋友,可以戳这里获取

    一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 7
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值