爬虫技术栈小结

Posted by 甘家城 on 2017-11-05 Viewed times

做了接近一个月爬虫,中间爬到数据多的爬过唯品会,dpchallenge,frilly。百度图片和1688也是取了一部分数据来。这里做一些爬虫技术总结记录,包括基本的requests使用,json,bs4,OrderedDict,下载图片,多进程以及post一个数组。

首先,基本的爬虫以唯品会(这里以女装做示范),主要用以接口获取json数据,json解析,json格式化。

首先获取一下他的分类列表,由于返回的是callback里的函数,便去掉前后一些字符然后json格式化。

req=requests.Session()
cateurl='https://category.vip.com/ajax/getCategory.php?callback=getCategory&tree_id=117'
pplist=req.get(cateurl).text
ppjson=json.loads(pplist[12:-1])
pparr=ppjson['data'][0]['children'][0]['children']

之后访问分类的具体页面,用一点正则到他的js里解析出productIds,解析json,然后再通过里面的每个productid的拼接构成一个url,获取到商品服装信息(这里可得缩略图)。再进入服装详情页,得到商品大图。

for item in pparr:
    searchurl='https://category.vip.com/'+item['url']
        sec1=req.get(searchurl
        jsonpic=re.findall(r'"productIds":(.*?),"',sec1.text)
        piclist=json.loads(jsonpic[0])
        for n in range(2):
            productIds='%2C'.join(map(str,piclist[50*n:(n+1)*50]))
            resp=req.get('https://category.vip.com/ajax/mapi.php?service=product_info&productIds='+productIds+'&warehouse=VIP_SH')
            projson=json.loads(resp.text)
            if cate > -5:
                for j in projson['data']['products']:
                    detail=req.get('https://detail.vip.com/detail-'+str(j['brandId'])+'-'+str(j['productId'])+'.html?f=ad')
                    match=re.findall(r'<a href="(.*?)" class="J-mer-bigImgZoom">',detail.text)
                    for url in match:
                        print(url)

插一个从网页下载图片到本地的小技巧

img=req.get(imageurl).content
with open('test.jpg','wb') as f:
    f.write(img)
    f.close()

dpchallenge.com,这是个摄影网站,除了爬图片还得爬摄影信息及评论,主要靠beautifulsoup和正则解析html文本。

这里先爬了信息,其中也包括图片地址。之后在把所有图下载下来。

这里做一部分beautifulsoup的记录

soup=BeautifulSoup(response.text,"lxml")
source_url=soup.find_all('标签',{'属性':'值(写True则代表有这个属性)'

另一个这里要注意的便是OrderedDict,由于python的object读取显示出来时会乱序或者并不是按写入的顺序显示的。所以需要用OrderedDict作代替

from collections import OrderedDict
test=OrderedDict()
test["c"]="1"
test["b"]="2"
test["a"]="3"
print(test)

最后这里在做一下爬虫期间所用的多进程的简单使用,这里用到了进程池以及进程锁:

from multiprocessing import Pool,Manager
def func(n,lock):
    with lock:
        print(n)
if __name__=="__main__":
    pool=Pool()
    lock=Manager().Lock()
    for i in range(10):
        pool.apply_async(func, (i,lock))#这边也可以加回调
    pool.close()
    pool.join()

最后考虑一个post时发现的问题,也是平常可能会忽略而出错的。

http://test.ganjiacheng.cn/testspider/test.php是一个返回post数据的接口

在js的jquery的ajax里,

$.post("./test.php",{du:"0",data:["1","2","3"]},function(data){
    console.log(data)
})
//结果:{"du":"0","data":["1","2","3"]}

而在python里

import requests
import json
post_data={
    "du":"0",
    "data":["1","2","3"],
}
res=requests.post('http://test.ganjiacheng.cn/testspider/test.php',data=post_data)
print(res.json())
#结果:{'du': '0', 'data': '3'}

也便是数组形式如[]在post传输过程是不能保持的,上面的post_data传输的信息形式应该如du=0&data%5B%5D=1&data%5B%5D=2&data%5B%5D=3。

后来用了拼接的方法来解决这个问题。

有待提升的地方,在有较多js操作及判断的网页中,要爬到对应信息需进行复刻同样的js操作,首先要读懂js,再来要自己实现一遍,对于综合能力要求还是比较高的。对于1688这种检测到爬虫的一些行为后会需要你登录后进行操作,虽然登录后通过chrome拿到cookie是可以使用的,但可能会有时限等限制。还有待探索!


版权声明:本文为原创文章,转载请注明出处和作者,不得用于商业用途,请遵守 CC BY-NC-SA 4.0协议。

支付宝打赏 微信打赏

赞赏一下