python学习笔记6---数据解析

xpath简介

xpath(XML Path Language)是一门在XML和HTML中查找信息的语言。

Xpath开发工具

1.Chrome插件Xpath Helper
点击浏览器右边三点—更多工具—扩展程序—chrome网上商店搜索该插件(需要翻墙,可能一次不能成功添加,多尝试即可)
2.Firefox插件Try Xpath
点击浏览器右边三横—附加组件—搜索插件—添加

Xpath语法

  • 谓语
    /bookstore/book[1] 选取bookstore下的第一个book子元素
    /bookstore/book[last()] 选取bookstore下倒数第二个book元素
    /bookstore/book[position()❤️] 选取bookstore下前两个book子元素
    //book[@price=10] 选取所有属性price=10的book元素
  • 通配符
    /bookstore/* 选取bookstore下所有子元素
    //book[@*] 选取所有带有属性的book元素

lxml解析库

lxml是c语言写的
1.使用lxml解析html字符串,使用lxml.etree.HTML进行解析

from lxml import etree
htmlElement = etree.HTML(text)
print(etree.tostring(htmlElement,encoding='utf-8').decode('utf-8'))

2.解析html文件,使用lxml.etree.parse进行解析

from lxml import etree
htmlElement = etree.parse("tencent.html")
print(etree.tostring(htmlElement,encoding='utf-8').decode('utf-8'))

parse函数默认使用XML解析器,如果碰到不规范的html代码时会解析错误,此时要自己创建html解析器

from lxml import etree
parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse("tencent.html",parser=parser)
print(etree.tostring(htmlElement,encoding='utf-8').decode('utf-8'))

lxml和xpath结合使用

1.xpath返回的是一个列表
获取所有tr标签

from lxml import etree

parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse("tencent.html",parser=parser)
trs=htmlElement.xpath("//tr")
for tr in trs:
    print(etree.tostring(tr,encoding='utf-8').decode('utf-8'))

2.获取第二个tr标签

from lxml import etree

parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse("tencent.html",parser=parser)
tr=htmlElement.xpath("//tr[2]")[0] #如果列表中只有一个元素,在后面加[0]可以获取列表内的元素
print(etree.tostring(tr,encoding='utf-8').decode('utf-8'))

3.获取所有class属性等于even的tr标签

from lxml import etree

parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse("tencent.html",parser=parser)
tr=htmlElement.xpath("//tr[@class='even']") #如果列表中只有一个元素,在后面加[0]可以获取列表内的元素
for tr in trs:
    print(etree.tostring(tr,encoding='utf-8').decode('utf-8'))

4.获取所有职位信息(纯文本)
当tenxun.html文件由文本文件更改后缀而成时,注意编码方式选择utf-8,而非默认的ANSI,否则会报错(oxc6)

from lxml import etree

parser = etree.HTMLParser(encoding='utf-8')
htmlElement = etree.parse("tenxun.html",parser=parser)
trs=htmlElement.xpath("//tr[position()>1]")

positions =[]
for tr in trs:

    href=tr.xpath(".//a/@href")[0] #.//加.表示获取这个元素(tr)下的所有a标签的内容
    fullurl = 'http://hr.tencent.com/'+href
    title = tr.xpath("./td[1]//text()")[0]
    category = tr.xpath("./td[2]/text()")[0]
    nums= tr.xpath("./td[3]//text()")[0]
    address = tr.xpath("./td[4]/text()")[0]
    pubtime = tr.xpath("./td[5]/text()")[0]

    position ={
        'url':fullurl,
        'title':title,
        'category':category,
        'nums':nums,
        'address':address,
        'pubtime': pubtime
}
    positions.append(position) #列表中添加多个字典
print(positions)

上述代码结果

[{'url': 'http://hr.tencent.com/position_detail.php?id=48445&keywords=python&tid=0&lid=0', 'title': 'WXG10-152 企业微信专项测试工程师(广州)', 'category': '技术类', 'nums': '1', 'address': '广州', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48446&keywords=python&tid=0&lid=0', 'title': '25925-NLP高级工程师(深圳)', 'category': '技术类', 'nums': '1', 'address': '深圳', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48448&keywords=python&tid=0&lid=0', 'title': '22989-自然语言处理平台高级工程师', 'category': '技术类', 'nums': '1', 'address': '深圳', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48441&keywords=python&tid=0&lid=0', 'title': '25663-腾讯云国际化业务后台开发(深圳)', 'category': '技术类', 'nums': '5', 'address': '深圳', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48428&keywords=python&tid=0&lid=0', 'title': '25929-高级机器学习工程师', 'category': '技术类', 'nums': '1', 'address': '上海', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48430&keywords=python&tid=0&lid=0', 'title': '23295-互娱游戏营销算法工程师', 'category': '技术类', 'nums': '1', 'address': '深圳', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48427&keywords=python&tid=0&lid=0', 'title': '30628-业务运维高级工程师', 'category': '技术类', 'nums': '1', 'address': '北京', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48418&keywords=python&tid=0&lid=0', 'title': 'TEG02-SDN开发工程师(深圳总部)', 'category': '技术类', 'nums': '2', 'address': '深圳', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48419&keywords=python&tid=0&lid=0', 'title': 'TEG02-SDN开发工程师(北京)', 'category': '技术类', 'nums': '1', 'address': '北京', 'pubtime': '2019-03-12'}, {'url': 'http://hr.tencent.com/position_detail.php?id=48414&keywords=python&tid=0&lid=0', 'title': 'TME-腾讯音乐测试开发组长(深圳)', 'category': '技术类', 'nums': '1', 'address': '深圳', 'pubtime': '2019-03-12'}]

豆瓣电影爬虫(正在上映)

import requests
from lxml import etree
# 抓取目标网站上的页面
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
'Referer':'https://www.google.com/_/chrome/newtab?ie=UTF-8'
}
url = 'https://movie.douban.com/cinema/nowplaying/changsha/'
response= requests.get(url,headers=headers)
# print(response.text) 如果出现乱码就用response.content
text =response.text
# 2将抓取下来的数据根据一定规则进行提取
html =etree.HTML(text)
ul = html.xpath("//ul[@class='lists']")[0] #因为有正在上映和即将上映模块ul的class都是lists,取第一个正在上映的内容就可以
lis = ul.xpath("./li") #ul下的所有子li
movies=[]
for li in lis:
    title=li.xpath("@data-title")[0]
    score=li.xpath("@data-score")[0]
    photo=li.xpath(".//img/@src")[0]
    movie ={
        'title':title,
        'score':score,
        'photo':photo
     }
     movies.append(movie)

print(movies)

电影天堂爬虫

from lxml import etree
import requests
#gb2312 是gbk的子集

BASE_DOMAIN = 'http://dytt.net'
headers={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
}
url ="http://www.ygdy8.net/html/gndy/dyzz/list_23_1.html"

resp = requests.get(url,headers=headers)
# print(resp.content.decode('gbk')) #查看网页源代码,查看charset是什么编码
text = resp.content.decode('gbk')
html=etree.HTML(text)

detail_urls = html.xpath("//table[@tbspan]//a[@href]") 
for detail_url in detail_urls:
    print(BASE_DOMAIN + detail_ulrs)

电影天堂之爬取详情页

将上述代码改写成函数,并添加爬取多页和解析页面详情的功能(代码有误)

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 10 18:31:06 2019

@author: admin
"""

from lxml import etree
import requests
#gb2312 是gbk的子集

BASE_DOMAIN = "http://dytt.net"
HEADERS={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36"
}


def get_detail_urls(url):
    resp = requests.get(url,headers=HEADERS)
    text = resp.text
    html=etree.HTML(text)   
    detail_urls = html.xpath("//table[@class='tbspan']//a/@href") 
    detail_urls =map(lambda url:BASE_DOMAIN+url,detail_urls)
    return detail_urls

def parse_detail_page(url):
    movie ={}
    response = requests.get(url,headers=HEADERS)
#    text = response.content.decode('gbk')
    text =response.text
#    print(text)
    html =etree.HTML(text)
#    print(html)    
    title = html.xpath("//div[@class='title_all']//font[@color='#07519a']/text()")[0]
    print(type(title))
    movie['title'] = title
    zoome = html.xpath("//div[@id='Zoom']")[0]
    imgs =zoome.xpath(".//img/@src")
    cover =imgs[0] #封面图片
    screeshot =imgs[1] #电影截图
    movie['cover']=cover
    movie['screeshot'] =screeshot
    
    infos =zoome.xpath('.//text()')

    
    def parse_info(info,rule):
        return info.replace(rule,"").strip()
    
    for index,info in enumerate(infos):    
        if info.startswith("◎年  代"):
            info =parse_info(info,"◎年  代")
            movie['year']=info
        elif info.startswith("◎产  地"):
            info =parse_info(info,"◎产  地")
            movie['country']=info
        elif info.startswith("◎类  别"): 
            info =parse_info(info,"◎类  别")
            movie['category']=info
        elif info.startswith("◎片  长"):
            info =parse_info(info,"◎片  长")
            movie['duration']=info
        elif info.startswith("◎导  演"):   
            info =parse_info(info,"◎导  演")
            movie['director']=info
        elif info.startswith("◎主  演"):
            info =parse_info(info,"◎主  演")
            actors=[info]
            for x in range(index+1,len(infos)):
                actor =info[x].strip()
                if actor.startswith("◎"):
                    break
                actors.append(actor)
            movie['actors']=actors
        elif info.startswith("◎简  介"):
            info =parse_info(info,"◎简  介")
            for x in range(index+1,len(infos)):
                profile =infos[x].strip()
                movie['profile']=profile
    download_url =html.xpath(".//td[bgcolor='#fdfddf']/a")           
    movie['download_url']=download_url
    return movie      
    

def spider():
    base_url = "http://www.ygdy8.net/html/gndy/dyzz/list_23_{}.html"  
    movies =[]
    for x in range(1,7):
        url  = base_url.format(x)
        detail_urls = get_detail_urls(url)
        for detail_url in detail_urls:
            
            movie =parse_detail_page(detail_url)
            movies.append(movie)
            print(movie)
        
        
if __name__ =='__main__':
    spider()   

甲的代码

#!/usr/bin/env python 
# -*- coding:utf-8 -*-

from lxml import etree
import requests
import sys
import importlib
importlib.reload(sys)


BASE_DOMAIN = 'https://www.dytt8.net'
firs_url = "https://www.dytt8.net/html/gndy/dyzz/list_23_1.html"
HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) '
                  'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3610.2 Mobile Safari/537.36'
}


def get_detail_urls(url):
    response = requests.get(url, headers=HEADERS)
    text = response.text
    html = etree.HTML(text)
    detail_urls = html.xpath("//table[@class='tbspan']//a/@href")
    detail_urls = map(lambda url:  BASE_DOMAIN+url, detail_urls)
    return detail_urls


def parse_detail_page(url):
    movie = {}
    response = requests.get(url, headers=HEADERS)
    text = response.content.decode('gbk', 'ignore')
    html = etree.HTML(text)
    title = html.xpath("//div[@class='title_all']//font[@color='#07519a']/text()")[0]
    movie['title'] = title
    zoomE = html.xpath("//div[@id='Zoom']")[0]
    imgs = zoomE.xpath(".//img")
    #print(title, url)
    cover = imgs[0]
    movie['cover'] = cover
    if len(imgs) >= 2:
        screenshot = imgs[1]
        movie['screenshot'] = screenshot

    def parse_info(info, rule):
        return info.replace(rule, "").strip()

    infos = zoomE.xpath(".//text()")
    for index, info in enumerate(infos):
        if info.startswith("◎年  代"):
            info = parse_info(info, "◎年  代")
            movie['year'] = info
        elif info.startswith("◎产  地"):
            info = parse_info(info, "◎产  地")
            movie['country'] = info
        elif info.startswith("◎类  别"):
            info = parse_info(info, "◎类  别")
            movie['category'] = info
        elif info.startswith("◎豆瓣评分"):
            info = parse_info(info, "◎豆瓣评分")
            movie['douban_rating'] = info
        elif info.startswith("◎片  长"):
            info = parse_info(info, "◎片  长")
            movie['duration'] = info
        elif info.startswith("◎导  演"):
            info = parse_info(info, "◎导  演")
            movie['director'] = info
        elif info.startswith("◎主  演"):
            info = parse_info(info, "◎主  演")
            actors = [info]
            for x in range(index+1, len(infos)):
                actor = infos[x].strip()
                #actor = actor.encode('gbk', 'ignore')
                if actor.startswith("◎"):
                    break
                actors.append(actor)
            #for actor in actors:
            #    print(actor.encode('gbk', 'ignore'))
        elif info.startswith("◎简  介 "):
            info = parse_info(info, "◎简  介 ")  #电影简介多段的情况
            profiles = []
            for x in range(index+1, len(infos)):
                profile = infos[x].strip()
                if profile.startswith("【下载地址】") or profile.startswith("◎"):
                    break
                else:
                    profiles.append(profile)
            movie['profile'] = ''.join(profiles)
            print(url)
            print(movie['profile'].encode('utf-8'))
    download_url = html.xpath("//td[@bgcolor='#fdfddf']/a/@href")[0]
    movie['download_url'] = download_url
    return movie

def spider():
    base_url = "https://www.dytt8.net/html/gndy/dyzz/list_23_{}.html"
    movies = []
    for x in range(1, 5):
        url = base_url.format(x)
        detal_urls = get_detail_urls(url)
        for detal_url in detal_urls:
            movie = parse_detail_page(detal_url)
            movies.append(movie)
            print(movie)

if __name__ == '__main__':
    spider()


甲的代码结果:

https://www.dytt8.net/html/gndy/dyzz/20190307/58312.html
b'\xe5\xbe\x97\xe7\x9f\xa5\xe5\xbc\x9f\xe5\xbc\x9f\xe5\x9c\xa8\xe7\xbd\x97\xe9\xa9\xac\xe5\xb0\xbc\xe4\xba\x9a\xe6\x89\xa7\xe8\xa1\x8c\xe4\xbb\xbb\xe5\x8a\xa1\xe4\xb8\xa7\xe5\x91\xbd\xe5\x90\x8e\xef\xbc\x8c\xe4\xb8\x80\xe4\xbd\x8d\xe9\x80\x80\xe4\xbc\x8d\xe5\x86\x9b\xe4\xba\xba\xe4\xb8\x8e\xe4\xb8\xa4\xe5\x90\x8d\xe7\x9b\x9f\xe5\x8f\x8b\xe8\x81\x94\xe6\x89\x8b\xe5\x90\x91\xe7\xa5\x9e\xe7\xa7\x98\xe7\x9a\x84\xe6\x95\x8c\xe4\xba\xba\xe5\xaf\xbb\xe4\xbb\x87\xe2\x80\xa6\xe2\x80\xa6'
{'title': '2019年动作《硬核风暴》BD中英双字幕', 'cover': <Element img at 0x192e1affcc8>, 'screenshot': <Element img at 0x192dda70dc8>, 'year': '2019', 'country': '美国', 'category': '动作/犯罪', 'douban_rating': '0/10 from 0 users', 'duration': '92分钟', 'director': '基翁尼·韦克斯曼 Keoni Waxman', 'profile': '得知弟弟在罗马尼亚执行任务丧命后,一位退伍军人与两名盟友联手向神秘的敌人寻仇……', 'download_url': 'ftp://ygdy8:[email protected]:8483/阳光电影www.ygdy8.com.硬核风暴.BD.720p.中英双字幕.mkv'}
。
。
。
https://www.dytt8.net/html/gndy/dyzz/20190219/58235.html
b'\xe8\x89\xbe\xe5\xbe\xb7\xe9\x87\x8c\xe5\xae\x89\xef\xbc\x88\xe9\xa9\xac\xe9\x87\x8c\xe5\xa5\xa5\xc2\xb7\xe5\x8d\xa1\xe8\x90\xa8\xe6\x96\xaf Mario Casas \xe9\xa5\xb0\xef\xbc\x89\xe7\xbb\x8f\xe8\x90\xa5\xe7\x9d\x80\xe4\xb8\x80\xe9\x97\xb4\xe7\xa7\x91\xe6\x8a\x80\xe5\x85\xac\xe5\x8f\xb8\xef\xbc\x8c\xe4\xba\x8b\xe4\xb8\x9a\xe8\x92\xb8\xe8\x92\xb8\xe6\x97\xa5\xe4\xb8\x8a\xef\xbc\x8c\xe5\xae\xb6\xe4\xb8\xad\xe6\x9c\x89\xe7\xbe\x8e\xe4\xb8\xbd\xe8\xb4\xa4\xe6\x83\xa0\xe7\x9a\x84\xe5\xa6\xbb\xe5\xad\x90\xe5\x92\x8c\xe6\xb4\xbb\xe6\xb3\xbc\xe5\x8f\xaf\xe7\x88\xb1\xe7\x9a\x84\xe5\xa5\xb3\xe5\x84\xbf\xef\xbc\x8c\xe4\xba\x8b\xe4\xb8\x9a\xe5\xae\xb6\xe5\xba\xad\xe5\x8f\x8c\xe4\xb8\xb0\xe6\x94\xb6\xe7\x9a\x84\xe4\xbb\x96\xe6\x98\xaf\xe6\x97\x81\xe4\xba\xba\xe7\xbe\xa1\xe6\x85\x95\xe7\x9a\x84\xe5\xaf\xb9\xe8\xb1\xa1\xe3\x80\x82\xe7\x84\xb6\xe8\x80\x8c\xef\xbc\x8c\xe9\x87\x8e\xe5\xbf\x83\xe5\x8b\x83\xe5\x8b\x83\xe7\x9a\x84\xe8\x89\xbe\xe5\xbe\xb7\xe9\x87\x8c\xe5\xae\x89\xe5\xb9\xb6\xe6\x9c\xaa\xe7\x8f\x8d\xe6\x83\x9c\xe7\x9c\xbc\xe5\x89\x8d\xe6\x9d\xa5\xe4\xb9\x8b\xe4\xb8\x8d\xe6\x98\x93\xe7\x9a\x84\xe7\x94\x9f\xe6\xb4\xbb\xef\xbc\x8c\xe4\xb8\x80\xe7\x9b\xb4\xe4\xbb\xa5\xe6\x9d\xa5\xef\xbc\x8c\xe4\xbb\x96\xe5\x92\x8c\xe4\xb8\x80\xe4\xbd\x8d\xe5\x90\x8d\xe5\x8f\xab\xe5\x8a\xb3\xe6\x8b\x89\xef\xbc\x88\xe8\x8a\xad\xe8\x8a\xad\xe6\x8b\x89\xc2\xb7\xe8\x93\x9d\xe5\xa6\xae B\xc3\xa1rbara Lennie \xe9\xa5\xb0\xef\xbc\x89\xe7\x9a\x84\xe5\xa5\xb3\xe6\x91\x84\xe5\xbd\xb1\xe5\xb8\x88\xe4\xbf\x9d\xe6\x8c\x81\xe7\x9d\x80\xe8\x82\x89\xe4\xbd\x93\xe5\x85\xb3\xe7\xb3\xbb\xe3\x80\x82\xe6\x9f\x90\xe6\x97\xa5\xe5\xb9\xbd\xe4\xbc\x9a\xe8\xbf\x87\xe5\x90\x8e\xef\xbc\x8c\xe4\xb8\xa4\xe4\xba\xba\xe9\xa9\xb1\xe8\xbd\xa6\xe7\xa6\xbb\xe5\xbc\x80\xe5\x88\xab\xe5\xa2\x85\xef\xbc\x8c\xe5\x8d\xb4\xe5\x9c\xa8\xe8\xb7\xaf\xe4\xb8\x8a\xe5\x8f\x91\xe7\x94\x9f\xe4\xba\x86\xe8\xbd\xa6\xe7\xa5\xb8\xef\xbc\x8c\xe4\xb8\xba\xe4\xba\x86\xe6\x8e\xa9\xe7\x9b\x96\xe4\xba\x8b\xe4\xbb\xb6\xe7\x9a\x84\xe7\x9c\x9f\xe7\x9b\xb8\xef\xbc\x8c\xe4\xb8\xa4\xe4\xba\xba\xe5\x86\xb3\xe5\xae\x9a\xe5\xb0\x86\xe5\x9c\xa8\xe8\xbd\xa6\xe7\xa5\xb8\xe4\xb8\xad\xe6\xad\xbb\xe5\x8e\xbb\xe7\x9a\x84\xe9\x9d\x92\xe5\xb9\xb4\xe4\xb8\xb9\xe5\xb0\xbc\xe5\xb0\x94\xe8\x81\x94\xe5\x90\x8c\xe4\xbb\x96\xe7\x9a\x84\xe8\xbd\xa6\xe4\xb8\x80\xe8\xb5\xb7\xe6\xb2\x89\xe5\x85\xa5\xe6\xb9\x96\xe5\xba\x95\xe3\x80\x82\xe4\xb9\x8b\xe5\x90\x8e\xef\xbc\x8c\xe5\x8a\xb3\xe6\x8b\x89\xe9\x81\x87\xe8\xa7\x81\xe4\xba\x86\xe4\xb8\x80\xe4\xbd\x8d\xe5\x96\x84\xe8\x89\xaf\xe7\x9a\x84\xe8\x80\x81\xe4\xba\xba\xef\xbc\x8c\xe8\x80\x81\xe4\xba\xba\xe5\xb0\x86\xe5\x8a\xb3\xe6\x8b\x89\xe5\x9d\x8f\xe6\x8e\x89\xe7\x9a\x84\xe8\xbd\xa6\xe6\x8b\x89\xe5\x9b\x9e\xe5\xae\xb6\xe4\xb8\xad\xe4\xbf\xae\xe7\x90\x86\xef\xbc\x8c\xe7\x84\xb6\xe8\x80\x8c\xef\xbc\x8c\xe4\xbb\xa4\xe5\x8a\xb3\xe6\x8b\x89\xe6\xb2\xa1\xe6\x9c\x89\xe6\x83\xb3\xe5\x88\xb0\xe7\x9a\x84\xe6\x98\xaf\xef\xbc\x8c\xe8\xbf\x99\xe4\xbd\x8d\xe8\x80\x81\xe4\xba\xba\xef\xbc\x8c\xe7\xab\x9f\xe7\x84\xb6\xe5\xb0\xb1\xe6\x98\xaf\xe4\xb8\xb9\xe5\xb0\xbc\xe5\xb0\x94\xe7\x9a\x84\xe7\x88\xb6\xe4\xba\xb2\xe3\x80\x82'
{'title': '2017年高分悬疑《看不见的客人》BD国西双语中英双字', 'cover': <Element img at 0x192dca24408>, 'screenshot': <Element img at 0x192dca24288>, 'year': '2017', 'country': '西班牙', 'category': '剧情/悬疑/惊悚/犯罪', 'douban_rating': '8.7/10 from 530518 users', 'duration': '106分钟', 'director': '奥里奥尔·保罗 Oriol Paulo', 'profile': '艾德里安(马里奥·卡萨斯 Mario Casas 饰)经营着一间科技公司,事业蒸蒸日上,家中有美丽贤惠的妻子和活泼可爱的女儿,事业家庭双丰收的他是旁人羡慕的对象。然而,野心勃勃的艾德里安并未珍惜眼前来之不易的生活,一直以来,他和一位名叫劳拉(芭芭拉·蓝妮 Bárbara Lennie 饰)的女摄影师保持着肉体关系。某日幽会过后,两人驱车离开别墅,却在路上发生了车祸,为了掩盖事件的真相,两人决定将在车祸中死去的青年丹尼尔联同他的车一起沉入湖底。之后,劳拉遇见了一位善良的老人,老人将劳拉坏掉的车拉回家中修理,然而,令劳拉没有想到的是,这位老人,竟然就是丹尼尔的父亲。', 'download_url': 'ftp://ygdy8:[email protected]:8393/阳光电影www.ygdy8.com.看不见的客人.BD.720p.国西双语中英双字.mkv'}

乙的代码

from lxml import etree
import requests

# 域名
BASE_DOMAIN = 'http://www.ygdy8.net'
# url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_1.html'

HEADERS = {
    'User_Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
}

def get_detail_urls(url):
    response = requests.get(url, headers=HEADERS)

    # response.text 是系统自己默认判断。但很遗憾判断错误,导致乱码出现。我们可以采取另外方式 response.content。自己指定格式解码
    # print(response.text)
    # print(response.content.decode('gbk'))
    # print(response.content.decode(encoding="gbk", errors="ignore"))
    text = response.content.decode(encoding="gbk", errors="ignore")

    # 通过 xpath 拿到每个电影的详情url
    html = etree.HTML(text)
    detail_urls = html.xpath("//table[@class='tbspan']//a/@href")

    detail_urls = map(lambda url:BASE_DOMAIN+url,detail_urls) #这句意思相当于下面一段代码:替换列表中的每一个url
    # def abc(url):
    #     return BASE_DOMAIN+url
    # index = 1
    # for detail_url in detail_urls:
    #     detail_url = abc(detail_url)
    #     detail_urls[index] = detail_url
    #     index+1

    return detail_urls


# 解析详情页面
def parse_detail_page(url):
    movie = {}
    response = requests.get(url,headers = HEADERS)
    text = response.content.decode('gbk', errors='ignore')
    html = etree.HTML(text)
    # title = html.xpath("//div[@class='title_all']//font[@color='#07519a']")  # 本行47行,下面已修改

   # 打印出 [<Element font at 0x10cb422c8>, <Element font at 0x10cb42308>]
   #  print(title)

    # 为了显示,我们需要转一下编码
    # for x in title:
    #     print(etree.tostring(x,encoding='utf-8').decode('utf-8'))

     # 我们是为了取得文字,所以修改47行
    title = html.xpath("//div[@class='title_all']//font[@color='#07519a']/text()")[0]
    movie['title'] = title

    zoomE = html.xpath("//div[@id='Zoom']") [0] # 求出共同的顶级容器,方便后面求职
    imgs = zoomE.xpath(".//img/@src") # 求出海报和截图
    cover = imgs[0]
    if len(imgs) > 1:
        screenshot = imgs[1]
        movie['screenshot'] = screenshot
    # print(cover)
    movie['cover'] = cover

    infos = zoomE.xpath(".//text()")

    for index,info in enumerate(infos):
        if info.startswith('◎年  代'):
            info = info.replace("◎年  代", "").strip() # strip 去掉空格
            movie['year'] = info
        elif info.startswith("◎产  地"):
            info = info.replace("◎产  地", "").strip()
            movie["country"] = info
        elif info.startswith("◎类  别"):
            info = info.replace("◎类  别", "").strip()
            movie["category"] = info
        elif info.startswith("◎豆瓣评分"):
            info = info.replace("◎豆瓣评分", "").strip()
            movie["douban_rating"] = info
        elif info.startswith("◎片  长"):
            info = info.replace("◎片  长","").strip()
            movie["duration"] = info
        elif info.startswith("◎导  演"):
            info = info.replace("◎导  演", "").strip()
            movie["director"] = info
        elif info.startswith("◎主  演"):
            actors = []
            actor = info.replace("◎主  演", "").strip()
            actors.append(actor)
            # 因为主演有很多个,再加上其在电影天堂中元素的特殊性,需要遍历一遍,在分别求出每一个演员
            for x in range(index+1,len(infos)): # 从演员 infos 开始遍历,求出每一个演员
                actor = infos[x].strip()
                if actor.startswith("◎"): # 也就是到了标签 的 ◎ 就退出
                    break
                actors.append(actor)
            movie['actor'] = actors
        elif info.startswith('◎简  介 '):

            # info = info.replace('◎简  介 ',"").strip()
            for x in range(index+1,len(infos)):
                if infos[x].startswith("◎获奖情况"):
                  break
                profile = infos[x].strip()
                movie['profile'] = profile
            # print(movie)
        elif info.startswith('◎获奖情况 '):
            awards = []
            # info = info.replace("◎获奖情况 ", "").strip()
            for x in range(index+1,len(infos)):
                if infos[x].startswith("【下载地址】"):
                    break
                award = infos[x].strip()
                awards.append(award)
            movie['awards'] = awards
            # print(awards)

    download_url = html.xpath("//td[@bgcolor='#fdfddf']/a/@href")[0]
    movie['download_url'] = download_url
    return  movie

def spider():
    movies=[]
    base_url = 'http://www.ygdy8.net/html/gndy/dyzz/list_23_{}.html'
    for x in range(1,8):
        url = base_url.format(x)
        detal_urls = get_detail_urls(url) 
        for detal_url in detal_urls: 
            movie = parse_detail_page(detal_url) 
            movies.append(movie) 
            print(movie)

if __name__ == '__main__':
    spider()

乙的结果

{'title': '2018年科幻动作《铁血战士》HD中英双字幕', 'screenshot': 'https://lookimg.com/images/2018/11/28/cirEt.jpg', 'cover': 'https://extraimage.net/images/2018/11/14/b0c1336e1e662538c3794a8ae301d4f0.jpg', 'year': '2018', 'country': '美国/加拿大', 'category': '动作/科幻/惊悚/冒险', 'douban_rating': '5.1/10 from 19621 users', 'duration': '107分钟', 'director': '沙恩·布莱克 Shane Black', 'actor': ['波伊德·霍布鲁克 Boyd Holbrook', '崔凡特·罗兹 Trevante Rhodes', '雅各布·特伦布莱 Jacob Tremblay', '科甘-迈克尔·凯 Keegan-Michael Key', '奥立薇娅·玛恩 Olivia Munn', '斯特林·K·布朗 Sterling K. Brown', '托马斯·简 Thomas Jane', '阿尔菲·艾伦 Alfie Allen', '杰克·布塞 Jake Busey', '伊冯娜·斯特拉霍夫斯基 Yvonne Strahovski', 'Brian A. Prince', '麦克·多普德 Mike Dopud', '尼尔迈特 Niall Matter', '加里·切克 Gary Chalk', '艾米·阿内克 Emy Aneke', '弗雷泽·艾奇逊 Fraser Aitcheson', '洛奇林·莫罗 Lochlyn Munro', '叶芳华 Françoise Yip', '里斯·威廉姆斯 Rhys Williams', '萨奇·布洛克勒班克 Sage Brocklebank', '肖恩·O.罗伯茨 Sean O. Roberts', '柯林·科里根 Colin Corrigan', '帕特里克·萨邦圭 Patrick Sabongui', '弗雷泽·科比特 Fraser Corbett', '阿隆·克拉文 Aaron Craven', '安德鲁·詹金斯 Andrew Jenkins'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:3157/阳光电影www.ygdy8.com.铁血战士.HD.720p.中英双字幕.mkv'}
{'title': '2018年剧情励志《兄弟班》BD国粤双语中字', 'screenshot': 'https://lookimg.com/images/2018/11/27/cYdz9.jpg', 'cover': 'https://extraimage.net/images/2018/11/27/9549f2f723af307f5f503c28b0bb74f9.jpg', 'year': '2018', 'country': '中国香港/中国', 'category': '剧情/励志', 'douban_rating': '5.9/10 from 639 users', 'duration': '100分钟', 'director': '陈友 Anthony Chan', 'actor': ['陈家乐 Carlos Chan', '于湉 Tan Yu', '王梓轩 Jonathan Wong Chee-hynn', '吴鹤谦', '林耀声 Yiu-Sing Lam', '邓加乐', '任达华 Simon Yam', '金燕玲 Elaine Jin', '惠英红 Kara Hui', '廖启智 Kai Chi Liu', '谭咏麟 Alan Tam', '钟镇涛 Kenny Bee', '钱小豪 Siu-hou Chin', '陈友 Anthony Chan', '彭健新 Kuen Sun Pang', '叶智强 Danny Yip'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:3156/阳光电影www.ygdy8.com.兄弟班.BD.720p.国粤双语中字.mkv'}
{'title': '2018年喜剧《拯救圣诞记》BD中英双字幕', 'screenshot': 'https://lookimg.com/images/2018/11/26/c0rEz.jpg', 'cover': 'https://extraimage.net/images/2018/11/24/7adabb9273cf8f9373e8ecff252e0883.jpg', 'year': '2018', 'country': '美国', 'category': '喜剧', 'douban_rating': '7.1/10 from 156 users', 'director': '克雷·卡提斯 Clay Kaytis', 'actor': ['金柏莱·威廉姆斯 Kimberly Williams', '库尔特·拉塞尔 Kurt Russell', '奥利弗·赫斯顿 Oliver Hudson', '犹大·刘易斯 Judah Lewis', '拉蒙尼·莫里斯 Lamorne Morris', '达比·坎普 Darby Camp', '劳伦·科林斯 Lauren Collins', '马丁·罗奇 Martin Roach', 'David Kohlsmith', 'Kayla Lakhani'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:8359/阳光电影www.ygdy8.com.拯救圣诞记.BD.720p.中英双字幕.mkv'}
{'title': '2018年高分获奖剧情《大象席地而坐》HD国语中字', 'screenshot': 'https://lookimg.com/images/2018/11/25/cftpg.jpg', 'cover': 'https://extraimage.net/images/2018/11/24/1d80f4162515e6d1874b8d693af35b5b.jpg', 'year': '2018', 'country': '中国', 'category': '剧情', 'douban_rating': '8.1/10 from 24552 users', 'duration': '230分钟(导演剪辑版)', 'director': '胡迁 Qian Hu', 'actor': ['彭昱畅 Yuchang Peng', '章宇 Yu Zhang', '王玉雯 Uvin Wang', '李从喜 Congxi Li', '董向荣 Xiangrong Dong', '王柠 Ning Wang', '赵燕国彰 Guozhang Zhao-Yan', '朱颜曼滋 Yanmanzi Zhu', '凌正辉 Zhenghui Ling', '王超北 Chaobei Wang', '王雪洋 Xueyang Wang'], 'profile': '满州里动物园有一头大象,每天坐在那里。为朋友出头的少年、为弟报仇的恶霸哥哥、身陷囹圄的女生,卡在世界灰暗的缝隙里无法脱身,却挣扎着去看大象。萧瑟寒冬的一天,绝望身影在不对称不平衡的影像中碰撞, 爆裂了压抑的沉郁,在粗糙布景、朦胧灯光的低成本制作中肆意蔓延。作者兼导演胡波 (笔名胡迁)首作,以青涩朴质与震撼感性,获柏林影展赏识入围论坛单元, 却是无法嵌合和谐主旋律的一块失落拼图。看不见大象是共同宿命,胡波骤然陨落,也成了这一代人的遗憾。', 'awards': ['第68届柏林国际电影节(2018)', '最佳处女作奖 特别提及 胡波', '最佳处女作奖(提名) 胡波', '费比西奖(国际影评人联盟奖) 论坛及新电影论坛最佳影片 胡波', '第55届台北金马影展(2018)', '金马奖 最佳剧情片', '金马奖 最佳男主角(提名) 彭昱畅', '金马奖 最佳改编剧本 胡波', '金马奖 最佳新导演(提名) 胡波', '金马奖 最佳摄影(提名) 范超', '金马奖 最佳原创配乐(提名)', '观众票选最佳影片', '第42届香港国际电影节(2018)', '观众票选大奖 胡波', ''], 'download_url': 'ftp://ygdy8:[email protected]:4103/阳光电影www.ygdy8.com.大象席地而坐导演剪辑版.HD.720p.国语中字.mkv'}
{'title': '2018年悬疑惊悚《网络谜踪》BD中英双字幕', 'screenshot': 'https://lookimg.com/images/2018/11/24/cu3yR.jpg', 'cover': 'https://extraimage.net/images/2018/10/17/da6562c11f0504286a8ff309dcc5e722.jpg', 'year': '2018', 'country': '美国/俄罗斯', 'category': '剧情/悬疑/惊悚', 'douban_rating': '8.5/10 from 92860 users', 'duration': '102分钟', 'director': '阿尼什·查甘蒂 Aneesh Chaganty', 'actor': ['约翰·赵 John Cho', '米切尔·拉 Michelle La', '黛博拉·梅辛 Debra Messing', '约瑟夫·李 Joseph Lee', '萨拉·米博·孙 Sara Mibo Sohn', '亚历克丝·杰恩·高 Alex Jayne Go', '梅金·刘 Megan Liu', '刘卡雅 Kya Dawn Lau', '多米尼克·霍夫曼 Dominic Hoffman', '西尔维亚·米纳西安 Sylvia Minassian', '梅丽莎·迪斯尼 Melissa Disney', '康纳·麦克雷斯 Connor McRaith', '科林·伍德尔 Colin Woodell', '约瑟夫·约翰·谢尔勒 Joseph John Schirle', '阿什丽·艾德纳 Ashley Edner', '考特尼·劳伦·卡明斯 Courtney Lauren Cummings', '托马斯·巴布萨卡 Thomas Barbusca', '朱莉·内桑森 Julie Nathanson', '罗伊·阿布拉姆森 Roy Abramsohn', '盖奇·比尔托福 Gage Biltoft', "肖恩·奥布赖恩 Sean O'Bryan", '瑞克·萨拉比亚 Ric Sarabia', '布拉德·阿布瑞尔 Brad Abrell', '加布里埃尔D·安吉尔 Gabriel D. Angell'], 'profile': '母亲去世了,全家的重担都落在了金的身上,坚强的他独自将女儿抚养长大,虽然玛格非常的听话懂事,但随着时间的推移,金还是渐渐感受到了和女儿之间的隔阂。一天,玛格在放学后没有按时回家,直到第二天早晨也毫无音信。', 'awards': ['第34届美国独立精神奖(2019)', '最佳男主角(提名) 约翰·赵', ''], 'download_url': 'ftp://ygdy8:[email protected]:3155/阳光电影www.ygdy8.com.网络谜踪.BD.720p.中英双字幕.mkv'}
{'title': '2018年黄渤舒淇王宝强喜剧《一出好戏》BD国语中字', 'screenshot': 'https://lookimg.com/images/2018/11/24/cognv.jpg', 'cover': 'https://extraimage.net/images/2018/09/22/437a0f0b4e3b9e8fc2712402bf46f15a.jpg', 'year': '2018', 'country': '中国', 'category': '剧情/喜剧', 'douban_rating': '7.3/10 from 275,024 users', 'duration': '134分钟', 'director': '黄渤 Bo Huang', 'actor': ['黄渤 Bo Huang', '舒淇 Qi Shu', '王宝强 Baoqiang Wang', '张艺兴 Yixing Zhang', '于和伟 Hewei Yu', '王迅 Xun Wang', '李勤勤 Qinqin Li', '李又麟 You-Lin Lee', '宁浩 Hao Ning', '管虎 Hu Guan', '梁静 Jing Liang', '徐峥 Zheng Xu', '陈德森 Teddy Chan', '张磊 Lei Zhang'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:8302/阳光电影www.ygdy8.com.一出好戏.BD.720p.国语中字.mkv'}
{'title': '2018年高分剧情音乐《一个明星的诞生》BD韩版中英双字幕', 'screenshot': 'https://lookimg.com/images/2018/11/24/co9Mr.jpg', 'cover': 'https://extraimage.net/images/2018/11/24/c5c9f46f1bea00c30dd49749c25e6882.jpg', 'year': '2018', 'country': '美国', 'category': '剧情 / 爱情 / 音乐', 'douban_rating': '7.3/10 from 8957 users', 'duration': '135分钟', 'director': '布莱德利·库珀 Bradley Cooper', 'actor': ['Lady Gaga', '布莱德利·库珀 Bradley Cooper', '山姆·艾里奥特 Sam Elliott', '安德鲁·戴斯·克雷 Andrew Dice Clay', '拉菲·格拉沃恩 Rafi Gavron', '安东尼·拉莫斯 Anthony Ramos', '大卫·查普尔 Dave Chappelle', '亚历克·鲍德温 Alec Baldwin', '布兰迪·卡莉 Brandi Carlile', '朗·瑞弗金 Ron Rifkin', '巴里·沙巴卡·亨利 Barry Shabaka Henley', '迈克尔·D·罗伯茨 Michael D. Roberts', '迈克尔·哈尔尼 Michael Harney', '威廉·贝利 Willam Belli', '格雷戈·格伦伯格 Greg Grunberg', '德瑞娜·德尼罗 Drena De Niro', '艾迪·格里芬 Eddie Griffin', '哈尔希 Halsey', '马修·利巴提克 Matthew Libatique', '路奈尔·坎贝尔 Luenell Campell', '唐·罗伊·金 Don Roy King', '马克·查普曼 Mark G. Chapman', 'Steven Ciceron', '阿曼达·菲尔茨 Amanda Fields', '阿尔弗雷德·加比杜林 Alfred Gabidullin', '弗雷德里克·基夫 Frederick Keeve'], 'profile': '本片是布莱德利·库珀生平第一次自编、自导、自演,并担任制片,挑战从来没有尝试过的现场演唱与音乐创作的电影。也是Lady Gaga首次挑战大银幕。其在影片中演唱的这些歌曲是由她跟布莱德利·库珀,还有几位艺人一起创作的。所有音乐都是原创和现场录音。', 'awards': ['第22届好莱坞电影奖(2018)', '年度摄影奖 马修·利巴提克', ''], 'download_url': 'ftp://ygdy8:[email protected]:4102/阳光电影www.ygdy8.com.一个明星的诞生.HD.720p.韩版中英双字幕.mkv'}
{'title': '2018年姜文彭于晏动作《邪不压正》HD国语中字', 'screenshot': 'https://lookimg.com/images/2018/11/23/cK5js.jpg', 'cover': 'https://extraimage.net/images/2018/11/23/2cb27ff4bde914968c55ad80035ba760.jpg', 'year': '2018', 'country': '中国', 'category': '剧情/喜剧/动作', 'douban_rating': '7.2/10 from 244586 users', 'duration': '137分钟', 'director': '姜文 Wen Jiang', 'actor': ['彭于晏 Eddie Peng', '廖凡 Fan Liao', '姜文 Wen Jiang', '周韵 Yun Zhou', '许晴 Qing Xu', '泽田谦也 Kenya Sawada', '安地 Andy Friend', '史航 Hang Shi', '李梦 Meng Li', '丁嘉丽 Jiali Ding', '陈曦'], 'profile': '本片根据张北海的小说《侠隐》改编。', 'awards': ['第55届台北金马影展(2018)', '金马奖 最佳导演(提名) 姜文', '金马奖 最佳女配角(提名) 许晴', '金马奖 最佳美术设计(提名) 柳青', '金马奖 最佳造型设计(提名) 张叔平/董仲民/王汁', '金马奖 最佳动作设计 何钧/谷垣健治/严华', '金马奖 最佳视觉效果(提名) 王绍帅/杨月娟', ''], 'download_url': 'ftp://ygdy8:[email protected]:3154/阳光电影www.ygdy8.com.邪不压正.HD.1080p.国语中字.mp4'}
{'title': '2018年惊悚动作《薄荷杀手》BD中英双字幕', 'screenshot': 'https://lookimg.com/images/2018/11/22/c21fJ.jpg', 'cover': 'https://extraimage.net/images/2018/11/20/eccfb0f5a34ce8ea0d7024af8d979afc.jpg', 'year': '2018', 'country': '美国', 'category': '剧情/动作/惊悚', 'douban_rating': '6.2/10 from 192 users', 'duration': '102分钟', 'director': '皮埃尔·莫瑞尔 Pierre Morel', 'actor': ['詹妮弗·加纳 Jennifer Garner', '小约翰·加拉赫 John Gallagher Jr.', '约翰·奥提兹 John Ortiz', '胡安·巴勃罗·拉瓦 Juan Pablo Raba', '安妮·伊隆泽 Annie Ilonzeh', '杰夫·赫普内尔 Jeff Hephner', '凯莱·弗莱明 Cailey Fleming', '埃迪·辛 Eddie Shin', '马索·曼恩 Method Man', '泰森·里特 Tyson Ritter', '伊恩·卡塞尔伯里 Ian Casselberry', '理查德·卡夫拉尔 Richard Cabral', '约翰尼·奥蒂斯 Johnny Ortiz'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:8421/阳光电影www.ygdy8.com.薄荷杀手.BD.720p.中英双字幕.mkv'}
{'title': '2018年动作《反贪风暴3》BD国粤双语中字', 'screenshot': 'https://lookimg.com/images/2018/11/22/c25jD.jpg', 'cover': 'https://extraimage.net/images/2018/10/26/a56f982b41186687fdc2e6eff6ebcc01.jpg', 'year': '2018', 'country': '中国香港', 'category': '剧情/动作/犯罪', 'douban_rating': '5.8/10 from 22378 users', 'duration': '97分钟', 'director': '林德禄 David Lam', 'actor': ['古天乐 Louis Koo', '张智霖 Julian Cheung', '郑嘉颖 Kevin Cheng', '邓丽欣 Stephy Tang', '栢天男 Adam Pak', '谢天华 Michael Tse', '张继聪 Louis Cheung', '夏嫣 Anika', '蔡瀚亿 Babyjohn Choi', '廖启智 Kai Chi Liu', '谭耀文 Patrick Tam', '卢海鹏 Hoi-Pang Lo', '罗兰 Lan Law', '麦长青 Cheung-Ching Mak', '张松枝 Deno Cheung', '陈庭欣 Toby Chan', '丁海峰 Haifeng Ding', '冯雷 Lei Feng', '李昕岳 Xinyue Li'], 'profile': '', 'download_url': 'ftp://ygdy8:[email protected]:8358/阳光电影www.ygdy8.com.反贪风暴3.BD.720p.国粤双语中字.mkv'}
{'title': '2018年获奖动画《幸福路上》BD国语中字', 'screenshot': 'https://lookimg.com/images/2018/11/22/c2FIg.jpg', 'cover': 'https://extraimage.net/images/2018/11/22/70f962d3d62cb8ca4f5d0c0724058778.jpg', 'year': '2017', 'country': '中国台湾', 'category': '动画', 'douban_rating': '7.6/10 from 1687 users', 'duration': '111分钟', 'director': '宋欣颖 Hsin-yin Sung', 'actor': ['桂纶镁 Lunmei Gwei', '魏德圣 Te-Sheng Wei', '陈博正 Bor Jing Chan', '廖慧珍 Hui-Jen Liao'], 'profile': '小琪 (桂綸鎂 聲演) 生於蔣介石逝世當天,成長過程正是台灣社會經歷最劇烈轉變的時期。 小琪六歲那年舉家搬到新北市幸福路,為了滿足父母期望,她力爭上游,但也許幸福本來就沒有捷徑。 她一步步走上當初沒預期的路,到美國工作、結婚,走到人生的瓶頸,因外婆去世,重返老家,回首童年過程中,慢慢思索自己走過的路:「長大了,我有成為理想中的大人嗎?」', 'awards': ['第55届台北金马影展(2018)', '金马奖 最佳改编剧本(提名) 宋欣颖', '金马奖 最佳动画长片 宋欣颖', '第20届台北电影节(2018)', '台北电影奖 百万首奖 宋欣颖', '台北电影奖 最佳动画片 宋欣颖', '台北电影奖 观众票选奖 宋欣颖', ''], 'download_url': 'ftp://ygdy8:[email protected]:7358/阳光电影www.ygdy8.com.幸福路上.BD.720p.国语中字.mkv'}

腾讯社会招聘python岗位

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 11 11:29:54 2019

@author: admin
"""
import requests
from lxml import etree

BASE_DOMAIN = "https://hr.tencent.com/"
HEADERS={
'User-Agent':"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36",
'Referer':'https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start=0'
}


def get_detail_urls(url):
    response  = requests.get(url,headers=HEADERS)
    text = response.text
    html = etree.HTML(text) 
    detail_urls = html.xpath("//table[@class='tablelist']//td[@class='l square']/a/@href")
    detail_urls = map(lambda url:BASE_DOMAIN+url, detail_urls) 
    return detail_urls

    
def parse_detail_page(url):
    position={}
    res = requests.get(url,headers = HEADERS)
    text =res.text
    html = etree.HTML(text)
    place = html.xpath("//tr[@class='c bottomline']/td[1]/text()")[0]
    position['place']=place
    catetory = html.xpath("//tr[@class='c bottomline']/td[2]/text()")[0]
    position['catetory']=catetory
    nums = html.xpath("//tr[@class='c bottomline']/td[3]/text()")[0]
    position['nums']=nums
    duties = html.xpath("//table[@class='tablelist textl']//tr[3][@class='c']//ul[@class='squareli']//text()")
    position['duties']=duties
    requirements = html.xpath("//table[@class='tablelist textl']//tr[4][@class='c']//ul[@class='squareli']//text()")
    position['requirements']=requirements
    return position
    
    
def spider():
    base_url = "https://hr.tencent.com/position.php?lid=&tid=&keywords=python&start={}"
    positions=[]
    for x in range(0,5):
        url  = base_url.format(x*10)
        detail_urls = get_detail_urls(url)
        for detail_url in detail_urls:
            
            position =parse_detail_page(detail_url)
            positions.append(position)
            print(position)

if __name__ =='__main__':
    spider()   

上述代码运行结果

{'place': '上海', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责车联网云平台基础产品内部运维体系建设,提升部署和运维质量及效率;', '负责基础产品运维,保障交付后的项目基础产品稳定性;', '负责平台技术指标数据分析,监控故障,统计分析业务质量;', '与架构师及研发团队配合,前期就一起参与系统架构设计,制定业务系统优化规划,提升系统效率和稳定性。', '在运维中总结提炼运维方法论及实践方案,不断提升基础产品运维能力,并反馈研发优化产品。'], 'requirements': ['本科及以上学历,计算机软件或相关专业,英语4级及以上;', '7年以上Java开发和Linux系统运维经验,熟悉Python、Shell语言;', '有公有云使用经验,如云主机、VPC,CLB,COS,CDN,短信,拨测,PSTN,点直播,云监控,云解析,各类安全防护等,腾讯云使用经验者优先;', '熟练对MYSQL,Redis,Kafka,MongoDB,Hadoop进行各项运维工作,有同步容灾经验;', '熟悉Jenkins,Ansible,SaltStack,ELK,Zabbix等DevOps/CI/CD工具链;', '有运维自动化、监控系统、发布系统、运维支撑系统等开发经验者优先;', '有良好的学习能力和技术钻研能力;', '有强烈的责任心和主动性;', '具备英语听说读写能力的优先;', '具备车联网平台基础运营经验优先;']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['手机游戏后台功能模块的设计和开发工作;', '手机游戏后台系统运营和问题分析和解决。'], 'requirements': ['计算机相关专业本科以上学历,具备Unix/Linux下C/C++ 2年以上开发经验; ', '精通TCP/IP协议,进程间通讯编程,熟悉Unix/Linux下常用架构设计方法; ', '熟悉Unix/Linux操作系统原理,熟练使用shell工具; ', '至少熟悉一种数据库的使用;', '熟悉Lua、Python或者其它脚本语言;', '有手机游戏开发经验的优先。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责行业tob 售后平台的服务体系建设、标准制定和改进优化,全流程内外部服务SLA流程建设;', '负责售后服务的全流程devops工具及流程建设和优化。', '负责业务系统部署方案评估、后台的搭建、部署、监控、故障处理、调优、升级、日常维护和管理工作;', '负责业务服务器系统部署、应用调整和优化,增强系统可用性;', '负责大流量,高并发系统下服务器系统部署方案的运维保障;', '带领团队完成以上工作,并且能够通过辅导等各种手段提升团队能力。'], 'requirements': ['有5年以上运维和服务器集群管理经验,2年以上团队管理经验;', '熟练使用Linux/unix操作系统,精通Shell编程,并熟练掌握Perl、PHP、Python之一的脚本编程,熟悉TCP/IP、HTTP等协议,有良好的网络、存储、安全、计算机体系结构方面的知识;', '熟悉Linux系统、Nginx、PHP、IPTABLES等,了解cvm,docker等虚拟化技术;', '熟悉MySQL、Redis、MongoDB运维及云平台日常操作,具备公有云相关运维经验优先考虑;', '熟练掌握docker相关技术,有docker平台开发或运维管理经验者优先;', '掌握Kubernetes、mesos等编排服务框架者优先;', '对运维工作兴趣浓厚,具备较强的运维技能。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['1. 负责搜索相关性模型建设,通过提取用户、资源、环境等多维度特征,优化相关性模型;', '2.建设 query2query,query2doc的相关性,提升搜索直达的召回率与准确率;', '3 使用 CNN 、DNN等业界新方法提升现有NLP相关能力;', '4. 负责相关人才培养。'], 'requirements': ['1. 计算机或相关专业本科及以上学历, 3年以上工作经验( 2年以上自然语言处理工作 ),', '2. 具备丰富的机器学习算法实践经验; ', '2. 熟悉 C++、java、scala、python等一门或多编程语言;', '3. 要求有机器学习 /数据挖掘 /信息检索 /深度学习/神经网络实践经验;', '4. 有智能助手、对话系统建设经验者优先; 系统建设经验者优先;', '5. 良好的逻辑思维能力和数据敏感度,从海量中发现有价值规律; ', '6. 能够阅读英文技术档和论,具有良好的自学力; ', '7. 有很强的技术选型及规划能力、较好沟通积极主动,愿意接受挑战强的技术选型及规划能力、较好沟通积极主动,愿意接受挑战,抗压能力好 。']}
{'place': '深圳', 'catetory': '产品/项目类', 'nums': '1人', 'duties': ['针对定制化的产品数据需求给出详尽的数据分析报告;', '与数据开发深度合作打造体系化的数据模型;', '设计分析,并解读各项ABTest实验和运营策略结果;', '制定和实现产品指标的持续性跟踪及报表产出;', '打造整体数据驱动生态意识。'], 'requirements': ['两年以上工作经验,统计数学背景学历优先;', '有数据驱动意识;', '扎实的编程基础(Pythonm R, Scala)和使用数据产品工具(R, SPSS, SQL, Tableu)的能力;', '有将数据转化成可理解和执行的决策(A/B test, 产品方案)能力;', '良好的团队合作意识。']}
{'place': '深圳', 'catetory': '产品/项目类', 'nums': '1人', 'duties': ['利用平台的海量数据发现可执行的方案来推动产品决策;', '传递数据驱动的可视化方案和建议给到业务对接人;', '和用研,产品,算法工程师深度合作;', '通过执行和分析A/B test来加快产品的实验和迭代。'], 'requirements': ['五年以上工作经验,统计数学背景学历优先;', '有数据驱动意识和相关产品分析决策项目的领导经验;', '扎实的编程基础(Pythonm R, Scala)和使用数据产品工具(R, SPSS, SQL, Tableu)的能力;', '有将数据转化成可理解和执行的决策(A/B test, 产品方案)能力;', '良好的团队合作意识。']}
{'place': '深圳', 'catetory': '产品/项目类', 'nums': '1人', 'duties': ['渠道建设:对渠道和用户增长的产品数据进行深度分析,建设分渠道的质量和ROI评估体系,为渠道、用户增长和新用户推荐策略提供洞察;', '数据分析:负责数据上报和数据体系建设;根据业务发展需求,挖掘用户数据价值,推动改善产品功能和提升运营效率;', '数据产品:负责QQ音乐大数据平台的产品策划与价值输出,通过大数据提升产品能力及对外输出商业化价值,包括但不限于BI系统、数据专题报告等。'], 'requirements': ['计算机、统计、数学等相关理工科专业,本科及以上学历;', '3年以上相关工作经历,有业内成熟的大数据产品从业经验(包含但不局限于增长黑客、BI、精准推荐与营销等)者优先,善于抽象和提炼在行业/角色/场景上的共性需求,掌握SQL/VBA/SPSS/Python等尤佳;', '关注互联网行业的发展动态,了解行业用户的行为习惯,如有持续关注垂直领域发展的经验亦可;', '系统思考、自我驱动,能够站在业务视角审视、发现并快速解决问题。']}
{'place': '北京', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责微信推荐系统文本关键词提取,分类,主题分析等自然语言处理工作', '负责微信推荐系统文本语义分析、知识图谱,大规模网络表示学习与异构网络建模等研究和优化工作;', '负责微信推荐深度学习语义推荐及平台系统建设等前沿探索工作。'], 'requirements': ['计算机相关专业硕士及以上学历,两年以上的互联网工作经验;', '熟练掌握C/C++,Java,python等编程语言,熟练使用linux环境;', '熟悉常用的自然语言处理、机器学习、数据挖掘算法,并有相关项目经验;', '参与过搜索引擎、推荐系统、对话系统和广告系统等线上系统者优先;', '参与过知识图谱、排序、点击率预估、语义匹配等模块的优先;', '责任心强,积极主动,勇于接受挑战,具有良好的团队合作和沟通能力。']}
{'place': '北京', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责位置服务的客户体系服务能力建设,包括官网控制台、CMS系统开发和维护工作;', '负责日常的Webservice API需求开发和维护工作,以及为各行业产品搭建平台化能力,提供通用一致性的地图能力输出; ', '负责位置服务产品后台接入层流量和权限控制服务开发和维护工作(该服务日PV峰值近百亿,QPS峰值20W),优化服务架构、提升服务性能和稳定性、保证服务质量;', '负责位置服务计费和增值能力开发和维护工作;', '负责团队日常规范制度的制定、优化和执行,提升工作效率、产品质量,降低安全风险、工作成本;', '负责后台技术发展规划、技术方案拟定、架构设计、代码质量把控、文档编写等工作。'], 'requirements': ['1.本科及以上学历,计算机相关专业,有地图开发相关经验者优先;', '2.三年以上Unix/Linux下C/C++开发经验,熟练掌握PHP/Python/NodeJS等至少一种脚本语言;', '3.对Mysql、Kafka、Redis,Hadoop,Spark等分布式存储、队列、计算、集群管理中的一项或多项有深入的理解和实战经验;', '4.具备大规模高并发分布式系统架构设计和优化经验,较强的对业务现状及问题的理解和分析能力,能够基于工程、架构、机器学习(optional)等技术视角去解决问题、优化效果;', '5.善于主动思考总结,倡导创新与持续优化,优秀的表达和沟通能力,热爱互联网,对待技术有强烈兴趣;', '6.有良好的团队合作意识及抗压能力,有强烈的主人翁意识推进事务进展。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '2人', 'duties': ['流程:负责整个腾讯云tob 售后平台的服务体系建设、标准制定和改进优化,全流程内外部服务SLA流程建设;', '服务:负责全国各区域售后服务的质量和服务能力管理;', '工具:负责售后服务的全流程devops工具及流程建设和优化。'], 'requirements': ['本科及以上学历,计算机或相关专业,3年以上Linux运维工作经验;熟练使用Bash、Python等脚本语言;', '1) 技术能力:对云计算平台有相对比较清楚的熟悉和了解,深入理解操作系统、tcp/IP协议,熟悉IaaS/PaaS等产品,对虚拟化/计算网络/安全/数据库/存储/大数据/docker/负载均衡/消息队列/k8s等至少要有1-2个方向比较深入的了解,熟练掌握shell/python,具有一定规模运营的能力;', '2) 服务保障:在服务/质量管理等方面有体系性理解,有相关流程、工具建设的能力,识别共性/重复性问题并破解核心矛盾提升团队效率,沉淀通用性的平台或服务能力,推动平台服务能力与工具不断改进优化;', '3) 故障处理:对系统故障和用户投诉有很强的问题处理和推动能力,熟练掌握和把控用户口碑提升;', '4) 沟通协调:具备良好的沟通协调及推动能力,以及极强的责任心;', '5) 精神面貌:富有激情与创造力。']}
{'place': '北京', 'catetory': '技术类', 'nums': '1人', 'duties': ['1.负责地理数据采集平台核心系统/模块的设计和研发;', '2.负责关键技术调研和设计实现;', '3.负责相关系统或模块文档的撰写。'], 'requirements': ['1. 硕士以上学历,计算机、GIS相关专业优先;', '2. 掌握常用的数据结构和算法;', '3. 熟练使用python脚本语言,熟悉linux编程环境;', '4. 具备大数据计算和处理经验优先,熟悉spark框架;', '5. 有上进心和求知欲,善于学习新事物;', '6. 有良好的沟通能力以及较强的分析问题和解决问题的能力;']}
{'place': '北京', 'catetory': '技术类', 'nums': '1人', 'duties': ['为腾讯打造高效、稳定、扩展性较强的LBS数据自动监控、发布系统;', '与团队产品、运营一起发挥创造力,提升数据质量和价值。'], 'requirements': ['极好的系统设计和编码能力,重视代码质量,思路清晰,问题导向,行动快速; ', '对Hadoop、Spark、Hive、Kafka、Redis等分布式存储、队列、计算、集群管理中的一项或多项有深入的理解和实战经验;', '较好的沟通能力,能快速理解业务,对数据敏感,并能主导项目的进度,保证团队产出; ', '熟悉Linux开发环境,熟悉C++、Python语言的优先;有LBS相关的系统设计、数据处理经验者优先']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['快速上手业务,并组织团队完成产品的质量体系构建和管理工作;', ' 招聘并构建测试团队,完成团队的建设和发展,实现良好的跨团队合作;', ' 优化、提高团队的测试效率和输出质量,主动发现问题并优化改善,做好过程和结果的积极反馈和团队的反思提升工作;', ' 承担团队的游戏运营品质和责任,关注并提升团队业绩;', ' 承担外网游戏品质责任,关注项目业绩。'], 'requirements': ['本科以上学历,有3年以上软件测试经验,有游戏测试经验者优先,具有快速熟悉业务流程和优化,并建立完善质量体系的能力;', ' 有过带领团队独立完成项目测试工作,做好工作中的问题挖掘和改善,带领团队提升业务熟悉度和技术能力的提升的经验;', ' 具备团队组建、团队人才培养、团队梯队建设和团队发展的经验,能够很好的进行团队内外的沟通和团队绩效提升;', ' 优秀的执行力和抗压能力,热爱游戏测试,乐于主动反馈和积极思考;', ' 熟悉至少一门开发或者脚本语言,C++、C、C#、php、python优先;', ' 熟悉主流操作系统原理(windows、linux、android)、网络协议等,有过前后端性能、安全、兼容等测试经验者优先。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责移动游戏的专项测试和测试工具的开发、维护和完善;', '负责移动游戏整体的质量把控,制定测试方案、计划、跟踪实施,监控项目外网质量并实施改进;', '负责收集和分析业务测试需求,探索更多的测试手段和维度,帮助提升部门的测试质量、效率和深度。'], 'requirements': ['本科以上学历,3年及以上软件开发或测试经验;', '熟练使用C/C++,具有Java、Python或PHP开发经验,能够独立完成测试工具/自动化工具开发; ', '熟练使用LINUX,熟悉TCP/IP、HTTP等网络编程协议; ', '具有安卓、IOS开发经验或机器学习实践经验优先; ', '具有基于unity、UE4引擎相关的开发经验尤佳。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['负责业务系统部署方案评估、后台的搭建、部署、监控、故障处理、调优、升级、日常维护和管理工作;负责业务服务器系统部署、应用调整和优化,增强系统可用性;负责大流量,高并发系统下服务器系统部署方案的运维保障;'], 'requirements': ['有2年以上运维和服务器集群管理经验;熟练使用Linux/unix操作系统,精通Shell编程,并熟练掌握Perl、PHP、Python之一的脚本编程,熟悉TCP/IP、HTTP等协议,有良好的网络、存储、安全、计算机体系结构方面的知识;熟悉Linux系统、Nginx、PHP、IPTABLES等,了解cvm,docker等虚拟化技术;熟悉MySQL、Redis、MongoDB运维及云平台日常操作,具备公有云相关运维经验优先考虑; 熟练掌握docker相关技术,有docker平台开发或运维管理经验者优先;掌握Kubernetes、mesos等编排服务框架者优先;对运维工作兴趣浓厚,具备较强的运维技能;', '岗位归属:深圳-腾讯大厦 腾讯云安全云鼎实验室']}
{'place': '深圳', 'catetory': '技术类', 'nums': '2人', 'duties': ['负责腾讯云泛互联网行业PAAS、SASS产品研发工作; ', '参与相关系统的架构设计和评审,参与项目的技术攻坚和优化; ', '参与系统文档的撰写、维护;', '负责为客户提供行业云端解决方案、架构优化方案 。'], 'requirements': ['计算机、通信相关专业本科以上学历;', '编程基本功扎实,精通Java,C/C++,Python,Go一种语言, 熟悉面向对象技术,设计模式;', '精通TCP/IP协议相关知识及网络编程;', 'linux服务器端软件开发经验; 精通Unix/Linux环境和系统编程,熟悉服务器编程模型;', '精通mysql数据库及相关编程;', '善于沟通及主动思考总结,倡导创新与持续优化,思路周密,代码严谨,对技术有强烈兴趣;', '有良好的团队合作及抗压能力,有强烈的主人翁意识推进事务进展;', '具备一定架构能力,熟悉数据,有大容量、高性能、分布式系统的设计开发经验。']}
{'place': '深圳', 'catetory': '技术类', 'nums': '1人', 'duties': ['计算机、通信相关专业本科以上学历;', '编程基本功扎实,精通Java,C/C++,Python,Go一种语言, 熟悉面向对象技术,设计模式;', '精通TCP/IP协议相关知识及网络编程;', 'linux服务器端软件开发经验;', '精通Unix/Linux环境和系统编程,熟悉服务器编程模型;', '精通mysql数据库及相关编程;', '善于沟通及主动思考总结,倡导创新与持续优化,思路周密,代码严谨,对技术有强烈兴趣;', '有良好的团队合作及抗压能力,有强烈的主人翁意识推进事务进展;', '具备一定架构能力,熟悉数据,有大容量、高性能、分布式系统的设计开发经验优先。'], 'requirements': ['计算机、通信相关专业本科以上学历;', '编程基本功扎实,精通Java,C/C++,Python,Go一种语言, 熟悉面向对象技术,设计模式;', '精通TCP/IP协议相关知识及网络编程;', 'linux服务器端软件开发经验; 精通Unix/Linux环境和系统编程,熟悉服务器编程模型;', '精通mysql数据库及相关编程;', '善于沟通及主动思考总结,倡导创新与持续优化,思路周密,代码严谨,对技术有强烈兴趣;', '有良好的团队合作及抗压能力,有强烈的主人翁意识推进事务进展;', '具备一定架构能力,熟悉数据,有大容量、高性能、分布式系统的设计开发经验优先。']}
{'place': '深圳', 'catetory': '产品/项目类', 'nums': '2人', 'duties': ['"1、本科以上学历,具备3年以上互联网产品工作经验,熟悉产品设计和用户交互工作流程。', '2、思维逻辑清晰,数据分析能力优秀,善于用数据驱动产品的优化升级。', '3、具有社交、社区、短视频等相关工作经验优先。', '4、善于思考, 善于沟通和团队协作。', '5、熟练使用 SQL 进行数据地查询与处理,有研发或数据分析背景优先;', '6、能快速理解业务,发掘业务细节和数据之间的联系;', '7、思维活跃,注重细节,关注从创意到执行的全过程;', '8、掌握 Tableau/R/Python 等分析工具尤佳。"'], 'requirements': ['1、数据驱动,参与目标的制定与拆分,负责微视的用户增长、留存、拉新、转化、ARPU 提升等产品设计,策略制定工作。', '2、与设计、开发人员高效合作,从产品概念策划到推动开发上线中起到关键角色,对增长目标负责。', '3、与运营、市场人员紧密配合, 推动营销策略的实施,发现助力业务拓展的机会点。', '4、对所负责的项目进行数据跟踪与数据分析,并结合客户研究及竞品调研,找到对应的提升方案。"']}

BeautifulSoup4库的基本介绍

lxml只局部遍历,而BeautifulSoup基于HTML DOM,会载入整个文档,解析整个DOM树,所以时间和内开销大很多,性能低于lxml。BeautifulSoup解析HTML比较简单,支持CSS选择器,python标准库中HTML解析器,也支持lxml的XML解析器。
几大解析工具对比:
解析速度:BeautifulSoup<lxml<正则
使用难度:BeautifulSoup<lxml<正则
python=》c
bs4=》lxml
在这里插入图片描述

from bs4 import BeautifulSoup
html = """
	    <table class="tablelist" cellpadding="0" cellspacing="0">
		    	<tr class="h">
		    		<td class="l" width="374">职位名称</td>
		    		<td>职位类别</td>
		    		<td>人数</td>
		    		<td>地点</td>
		    		<td>发布时间</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48445&keywords=python&tid=0&lid=0">WXG10-152 企业微信专项测试工程师(广州)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>广州</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48446&keywords=python&tid=0&lid=0">25925-NLP高级工程师(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48448&keywords=python&tid=0&lid=0">22989-自然语言处理平台高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48441&keywords=python&tid=0&lid=0">25663-腾讯云国际化业务后台开发(深圳)</a></td>
					<td>技术类</td>
					<td>5</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48428&keywords=python&tid=0&lid=0">25929-高级机器学习工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>上海</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48430&keywords=python&tid=0&lid=0">23295-互娱游戏营销算法工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48427&keywords=python&tid=0&lid=0">30628-业务运维高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48418&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(深圳总部)</a></td>
					<td>技术类</td>
					<td>2</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48419&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(北京)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48414&keywords=python&tid=0&lid=0">TME-腾讯音乐测试开发组长(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    </table>
"""
bs=BeautifulSoup(html,"lxml")
print(bs.prettify) #以美化的方式打印,且自动添加<html> <body>标签

BeautifulSoup4库提取数据详解

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 12 20:33:03 2019

@author: admin
"""

from bs4 import BeautifulSoup
html="""
	    <table class="tablelist" cellpadding="0" cellspacing="0">
	         <tbody>
		    	<tr class="h">
		    		<td class="l" width="374">职位名称</td>
		    		<td>职位类别</td>
		    		<td>人数</td>
		    		<td>地点</td>
		    		<td>发布时间</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48445&keywords=python&tid=0&lid=0">WXG10-152 企业微信专项测试工程师(广州)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>广州</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48446&keywords=python&tid=0&lid=0">25925-NLP高级工程师(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48448&keywords=python&tid=0&lid=0">22989-自然语言处理平台高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48441&keywords=python&tid=0&lid=0">25663-腾讯云国际化业务后台开发(深圳)</a></td>
					<td>技术类</td>
					<td>5</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48428&keywords=python&tid=0&lid=0">25929-高级机器学习工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>上海</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48430&keywords=python&tid=0&lid=0">23295-互娱游戏营销算法工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48427&keywords=python&tid=0&lid=0">30628-业务运维高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48418&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(深圳总部)</a></td>
					<td>技术类</td>
					<td>2</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48419&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(北京)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a id="test" class="test"target="_blank" href="position_detail.php?id=48414&keywords=python&tid=0&lid=0">TME-腾讯音乐测试开发组长(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
              </tbody>
		    </table>
"""
soup = BeautifulSoup(html,'lxml')
# 1.获取所有tr标签
trs  = soup.find_all('tr')
for tr in trs:
    print(tr)
# 2.获取第2个tr标签
tr = soup.find_all('tr',limit=2)[1] #限制提取多少个标签
print(tr)
# 3.获取所有class等于even的tr标签
trs = soup.find_all('tr',class_='even')   #class_与class关键字区分,trs = soup.find_all('tr',attrs={'class':'even'}
for tr in trs:
    print(tr)
# 4.将所有id等于test,class也等于test的a标签提取出来
alist = soup.find_all('a',id='test',class_='test')  # alist= soup.find_all('a',attrs={'class':'test','id':'test'}
for a in alist:
    print(a)
# 5.获取所有a标签的href属性
alist = soup.find_all('a')
for a in alist:
    print(a['href'])  #print(a.attrs['href']
# 6.获取所有职位信息(纯文本)
trs =soup.find_all('tr')[1:]   
positions =[]
for tr in trs:
    position={} #每次循环都将这5个字段赋值给新的字典,并将这个字典添加到列表中(流水的字典,铁打的列表)
#    方法①
#    tds = tr.find_all('td')
#    title =tds[0].string
#    category =tds[1].string
#    nums =tds[2].string
#    city =tds[3].string
#    time =tds[4].string                    
#
#    position['title']=title
#    position['category']=category
#    position['nums']=nums
#    position['city']=city
#    position['time']=time
#    positions.append(position)    
    
    
#    方法②
    infos =list(tr.stripped_strings) #去掉\n  
    
    position['title']=infos[0]
    position['category']=infos[1]
    position['nums']=infos[2]
    position['city']=infos[3]
    position['time']=infos[4]
    positions.append(position)     
    
print(positions)        
    

CSS常用选择器

<!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
        .line{
        background-color:pink;
               } # 根据类名
         .box p{} #所有子孙元素0,1,2,3,4
         p{} #根据标签名称
         .box > p{} #子元素1,2,3行
         #line3{} #根据id名
         input[name='username'] #根据属性
         div.line{} #只选择div中class为line的标签
         div#line3{} #只选择div中id为line3的标签
    </style>
</head>
<body>
    <div class="box">
        <div >
            <p>第0行</p>
        </div>
        <p class="line'>第1行</p>
        <p class="line'>第2行</p>
        <p id="line3'>第3行</p>   
    </div>
    <p>第4行</p>
    <form>
        <input type="text" name="username">
    </form> 
</body>
</html>

select的css选择器提取元素

BeautifulSoup下的select和find_all用法类似

from bs4 import BeautifulSoup
html="""
	    <table class="tablelist" cellpadding="0" cellspacing="0">
	         <tbody>
		    	<tr class="h">
		    		<td class="l" width="374">职位名称</td>
		    		<td>职位类别</td>
		    		<td>人数</td>
		    		<td>地点</td>
		    		<td>发布时间</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48445&keywords=python&tid=0&lid=0">WXG10-152 企业微信专项测试工程师(广州)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>广州</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48446&keywords=python&tid=0&lid=0">25925-NLP高级工程师(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48448&keywords=python&tid=0&lid=0">22989-自然语言处理平台高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48441&keywords=python&tid=0&lid=0">25663-腾讯云国际化业务后台开发(深圳)</a></td>
					<td>技术类</td>
					<td>5</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48428&keywords=python&tid=0&lid=0">25929-高级机器学习工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>上海</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48430&keywords=python&tid=0&lid=0">23295-互娱游戏营销算法工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48427&keywords=python&tid=0&lid=0">30628-业务运维高级工程师</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48418&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(深圳总部)</a></td>
					<td>技术类</td>
					<td>2</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="even">
		    		<td class="l square"><a target="_blank" href="position_detail.php?id=48419&keywords=python&tid=0&lid=0">TEG02-SDN开发工程师(北京)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>北京</td>
					<td>2019-03-12</td>
		    	</tr>
		    			    	<tr class="odd">
		    		<td class="l square"><a id="test" class="test"target="_blank" href="position_detail.php?id=48414&keywords=python&tid=0&lid=0">TME-腾讯音乐测试开发组长(深圳)</a></td>
					<td>技术类</td>
					<td>1</td>
					<td>深圳</td>
					<td>2019-03-12</td>
		    	</tr>
              </tbody>
		    </table>
"""
soup = BeautifulSoup(html,'lxml')
# 1.获取所有tr标签
trs  = soup.select('tr')
for tr in trs:
    print(tr)
# 2.获取第2个tr标签
tr = soup.select('tr')[1] #限制提取多少个标签
print(tr)
# 3.获取所有class等于even的tr标签
trs = soup.select("tr[class='even']")   #class_与class关键字区分,trs = soup.select(".even"}
for tr in trs:
    print(tr)
# 4.将所有id等于test,class也等于test的a标签提取出来
css中不能同时对id和class筛选
# 5.获取所有a标签的href属性
alist = soup.select('a')
for a in alist:
    print(a['href'])  #print(a.attrs['href']
# 6.获取所有职位信息(纯文本)
trs =soup.select('tr')  
for tr in trs:
    infos=list(tr.stripped_strings)
    print(infos)   

BeautifulSoup拾遗

BeautifulSoup将复杂HTML文档转换为一个复杂的树形结构,每个节点都是python对象,所有对象可以归纳为4中:1.Tag 2.NavigableString 3.BeautifulSoup 4.Comment
Tag:BeautifulSoup中所有标签都是Tag类型,并且BeautifulSoup的对象本质上也是Tag类型。find_all等方法其实是Tag的
navigableSring:继承自python的str
BeautifulSoup:继承自Tag
Comment:继承自NavigableString

from bs4.element import Tag,NavigableString,comment

中国天气网

import requests
from pyecharts import Bar

ALL_DATA=[]
def parse_page(url):    
    
    headers={
        "User-Agent":'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) '
                     'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3610.2 Mobile Safari/537.36'
        }
    response=requests.get(url,headers=headers)
    text = response.content.decode('utf-8')
#    soup = BeautifulSoup(text,'lxml')
    soup = BeautifulSoup(text,'html5lib') # 港澳台地区表格不规范
    conMidtab = soup.find('div',class_='conMidtab') #存放某区域中的所有省份
    tables = conMidtab.find_all('table') #每一个table包含一个省份
    for table in tables:
        trs = table.find_all('tr')[2:]
        for index,tr in enumerate(trs):
            tds=tr.find_all('td')
            city_td=tds[0]
            if index==0:
                city_td=tds[1]
            city=list(city_td.stripped_strings)[0]
            temp_td =tds[-2]
            min_temp=list(temp_td.stripped_strings)[0]
            ALL_DATA.append({"city":city,"min_temp":int(min_temp)})

    
def main():
#    url="http://www.weather.com.cn/textFC/hb.shtml"
#    url="http://www.weather.com.cn/textFC/db.shtml"
#    url="http://www.weather.com.cn/textFC/hd.shtml"
#    url="http://www.weather.com.cn/textFC/hz.shtml"
#    url="http://www.weather.com.cn/textFC/hn.shtml"
#    url="http://www.weather.com.cn/textFC/xb.shtml"
#    url="http://www.weather.com.cn/textFC/xn.shtml"
    urls=[      
            
            "http://www.weather.com.cn/textFC/hb.shtml",
            "http://www.weather.com.cn/textFC/db.shtml",
            "http://www.weather.com.cn/textFC/hd.shtml",
            "http://www.weather.com.cn/textFC/hz.shtml",
            "http://www.weather.com.cn/textFC/hn.shtml",
            "http://www.weather.com.cn/textFC/xb.shtml",
            "http://www.weather.com.cn/textFC/xn.shtml" ,           
            "http://www.weather.com.cn/textFC/gat.shtml"         
          
          ]
    
    for url in urls:
        parse_page(url)
    # 根据最低气温排序
    ALL_DATA.sort(key=lambda data:data['min_temp'])
    data = ALL_DATA[0:10]
    cities = list(map(lambda x:x['city'],data))
    temps = list(map(lambda x:x['min_temp'],data))
    chart = Bar("中国天气最低气温排行榜")
    chart.add('',cities,temps) #第一个系列,第二个横坐标,第三个纵坐标
    chart.render('temperature.html')
    
if __name__=='__main__':
    main()
    

正则表达式匹配单个字符

  1. .匹配任意字符,但不能匹配换行符
  2. \d匹配任意数字(0-9),也可以[0-9]
  3. \D匹配任意非数字,也可以1
  4. \s匹配空白字符(\n,\t,\r,空格)
  5. \w匹配a-z,A-Z,数字和下划线,也可以是[0-9a-zA-Z_]
  6. \W匹配与\w正好相反,也可以是2
  7. []组合方式,只要满足[]中的字符就可以

正则表达式匹配多个字符

*匹配0个或多个任意字符
+匹配1个或多个任意字符
?匹配0个或1个
{m}匹配m个字符
{m,n}匹配m至n个

正则表达式小案例

1.手机号码

import re
text = "12345678910"
ret =re.match('1[34578]\d{9}',text)
print(ret.group())

2.邮箱

import re
text = "[email protected]"
ret =re.match('\w+@[a-z0-9]+\.[a-z]+',text)
print(ret.group())

3.URL

import re
text = "https://baike.baidu.com/item/python/49878?fr=aladdin"
ret =re.match('(http|https|ftp)://[^\s]+',text)
print(ret.group())

4.身份证

import re
text='42102319931215655x'
ret=re.match('\d{17}[xX0-9]',text)
print(ret.group())

5.0-100间的数字(09不能出现)

import re
text="99"
ret = re.match('[1-9]\d?$|100$',text)
print(ret.group())

正则表达式开始结束和或语法

  1. $:以。。。结尾
  2. ^:以。。。开头或者取反
  3. 默认贪婪模式,非贪婪模式在后面加?

转义字符和原生字符

正则表达式(不分语言)和python中都用\来做转义字符。如果要匹配出,需要4个\

text="apple \c"
ret=re.search('\\\\c',text)
print(ret.group())
text='\c'
ret=re.match(r'\\c',text) # r只是针对python,不对后面的内容进行转义,但这又属于正则表达式,所以\\c只交给正则表达式进行转义
print(ret.group())

得到\c

正则表达式的group分组

分组以圆括号形式表示
group()和group(0)等价,返回满足整个条件的字符串
groups返回里面的子分组,索引从1开始
group(1)返回第一个分组,可以传入多个

text='apple price is $99,orange price is $10'
ret =re.search(r".*(\$\d+).*(\$\d+)",text)
print(ret.group())
print(ret.group(0))#apple price is $99,orange price is $10
print(ret.group(1))#$99
print(ret.group(2))#$10
print(ret.groups())#('$99','$10')

正则表达式re常用模块

compile

  1. 经常要用到的正则表达式,用compile编译,执行效率更快
  2. 指定re.VERBOSE,做注释
r= re.compile(
r"""
\d+ #小数点前的数字
\.? #小数点
""",re.VERBOSE)

古诗文正则表达式爬取

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 25 15:34:55 2019

@author: admin
"""

import requests
import re


def parse(url):
    headers={'User_Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
             }
    response = requests.get(url,headers)
    text = response.text
    # 1.用分组只提取括号内的内容,否则提取第一个参数的所有字符,包括标签
    # 2.\s表示空格
    # 3..*包含除换行外的所有字符,re.DOTALL则包含所有字符
    titles = re.findall(r'<div\sclass="cont">.*?<b>(.*?)</b>',text,re.DOTALL)
    dynasties = re.findall(r'<p\sclass="source"><a.*?>(.*?)</a>',text,re.DOTALL)
    authors =re.findall(r'<p\sclass="source"><a.*?>.*?</a>.*?<a.*?>(.*?)</a>',text,re.DOTALL)
    
    # div中显示先id后class,但是复制粘贴显示先class后id
    content_tags = re.findall(r'<div class="contson" .*?>(.*?)</div>',text,re.DOTALL)
    contents=[]
    for content in content_tags:
        x= re.sub(r'<.*?>',"",content)
        contentppend(x.strip())
    #value=(1,2,3)
    #a,b,c =value  则a=1,b=2,c=3
    poems=[]
    for value in zip(titles,dynasties,authors,contents):
        titles,dynasties,authors,contents =value
        poem={
                'titles':titles,
                'dynasties':dynasties,
                'authors':authors,
                'content':content
                
                }
        poems.append(poem)
    for poem in poems:
        print(poem)
        print('--'*20)
def main():
#    url = "https://www.gushiwen.org/default_1.aspx"
    for x in range(1,11):
        url="https://www.gushiwen.org/default_%s.aspx" % x
        parse(url)


if __name__=="__main__":
    main()
    

正则表达式之糗事百科段子

# -*- coding: utf-8 -*-
"""
Created on Tue Mar 26 10:21:48 2019

@author: admin
"""

import requests
import re

def parse_page(url):
    headers={'User_Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36'
             }
    response = requests.get(url,headers)
    text = response.text
    users = re.findall(r'<div\sclass="author clearfix">.*?<h2>(.*?)</h2>',text,re.S)
    content_tags = re.findall(r'<div\sclass="content">.*?<span>(.*?)</span>',text,re.S)
    duanzi =[]
    for content in content_tags:        
        x = re.sub(r'<.*?>',"",content)
        duanzi.append(x.strip())
        print(x.strip())
        print('--'*20)
        
    contents_totall=[]
    for value in zip(users,content_tags):
        users,content_tags=value
        content_totall={
                'users':users,
                'content_tags':content_tags
                
                }
        contents_totall.append(content_totall)
        
    for content_totall in contents_totall:
        print(content_totall)    
        print('--'*20)

def main():
#    url="https://www.qiushibaike.com/text/page/1/"
    for x in (1,11):
        url="https://www.qiushibaike.com/text/page/%s/" % x
        parse_page(url)


if __name__=='__main__':
    main()

  1. 0-9 ↩︎

  2. 0-9a-zA-Z_ ↩︎

猜你喜欢

转载自blog.csdn.net/qq_32482091/article/details/88359702