* 匹配前面的字符 0 或无限次
+ 匹配前面的字符1 或无限次
? 匹配前面的字符0 或1
{n} 匹配前面的字符n次
{n,} 匹配前面的字符最少n次
{n,m} 匹配前面的字符最少n次,最多m次
括号的作用
(1)、将原子1,2,3,4,5,6 a, b, d变成大原子
(2).在括号可以│ 或的关系
(3).反向引用replace
(4).^[\(].*?[\)]$ ^与$共同确定首尾数据
(5). [^\(] 匹配除( 以外的字符
(6). *? 大部分都要考虑,?存在的意义,如果有?,则说明有很大的可能,当前匹配的部分字符是允许不存在的。
(7). [\S]* 在数据前面可以添加?,但在后面的数据,要省略?。否则无法获取的后面的数据。如果有?,则会直接忽略。
(8). (.+?)[=](.*)? (.+?)[=](.*)?
中国号的作用:
[]只能匹配一个字符,不允许不同的字符出现在同一个[]内,大小写除外
表示范围,一般会与[]一起使用,点号 [.] 或\. 空格可以使用[ ]
注意:
1. ()组成的原子、[]组成 的单字符,.等代表的单字符 后面都可以 使用限定符
()一般是单字符,()一般是多字符,组成的大原子 ,但也可以是单字符
2.直接使用正则表达式,不需要/ .../ig
3. res = re.findall(r'url(.*?)',new_str)
注意括号的使用,因为是使用在re.findall(),里面不要有多余的空格 ,
每个括号都会被匹配成一个结果,最后返回的是由元组组成的列表,而不是字符串组成的列表,
4. res = re.sub(r'url(.*?)',' \\1:\\2 .js',new_str)
前面匹配的是原字符串的正则表达式,后面是替换的目标对象,\\n是匹配到的原字符串
正则表达式没有匹配到结果,则不会进行替换操作,只返回原字符串
5. pattern = re.compare(r'(\w+)(\w+)')
将正则表达式编译成pattern对象
6. res = re.match(pattern,new_str)
匹配数据,开头如果匹配失败就立刻返回None,
7. res = re.search(pattern,new_str).group()
查找数据,前面的search返回的是一个对象,匹配失败会返回None,常用作查找数据是否存在 slash_exist !=None
group()返回的是匹配的字符串,
8. list = re.split(pattern,'xxx')
通过正则表达式分割字符串,并返回一个列表,对于不确定的字符分割很有效
例子:
(1. [(\')|(\")] 表示' 或 "中一个 表示
(2. [0-9](1,3}(\ .[0-9]{1,3} ){3} 匹配127.0.0.1
(3. items = re.findall(r'([\w]+?[.]css)', items)[0] 匹配xxx.css, 单字符尽量使用[]而不是(),
单词字符只有一个字符,并不能单独使用去匹配一个完整的单词
(4. host = re.findall(r'((http[s]?)|(ftp))+(://)(([\w]+?[.])+([\w]+){1})[/]?',url) 匹配网址url的域名
host = re.findall(r'((http[s]?)|(ftp))+(://)([\S]+?)[/]',url) 和上面是相同的效果
pre_url = re.findall(r'((http[s]?)|(ftp))+(://)(([\w]+?[.])+([\w]+){1})([/]+([\S]+?[.]{1}[\w]*)+?)*',url)
获取网址的域名
pre_url = re.findall(r'((http[s]?)|(ftp))+(://)(((\w|-|_)+?[.])+((\w|-|_)*){1})(([/]+([\S]+?[.]?[\S]*)+?)*([/]?[?]?)?)?',url)
获取网址的所有信息
实战:
import re
headers_str='''
bootstrap.min.js
bootstrap.css
bootstrap-icons.css
'''
pattern = '(.+?)[.]js'
1 2
for line in headers_str.splitlines():
res = re.sub(pattern,'\\1.js',line)
print(res)
from bs4 import BeautifulSoup
三、BeautifulSoup.bs4模块
1.find返回第一个标签,
2.find_all返回一个列表,包含所有标签
3.find_all和find使用 (标签,class_='类名'),选择指定节点。
4.都有.get('xxx')方法 .get_text('xxx')方法 .text方法 .标签["属性"] 方法, 获取属性或者内容
5.使用 “.标签” 获取标签的子节点
1.select 是selector css选择器,可以根据css选择器语句选择节点,可以包含路径。
注意:但这与Selector的css选择器不一样。
2.select可以使用路径,但返回的是一个列表。
并且可以使用.get(), .get_text(),.text方法, 可以和find类型进行混合使用。
3..print.printify()格式化打印
下面的是等价的
div_list = dom_tree.select('div.quote')
div_list = dom_tree.find_all('div',class_='quote')
soup = BeautifulSoup(music_res.text,'lxml')
html.parser或者'lxml'
print(soup.title) # soup.title.string 获得标题 # soup.title获得标题标签(文本加标签<>)
print(soup.a['href']) # soup.a['href'],获取第一个a标签的href属性
print(soup.find('a').get('href')) # soup.find('a').get('href') 获取第一个a标签的href属性
print(soup.find_all('a')) # find_all['a'] 可以获取所有a标签,返回一个列表。
for s in soup.find_all('a'): # .get('href') 可以获取a标签下的href属性
print(s.get_text('href')) # .get_text('href')可以获取a标签href属性所在行的文本内容
print(s.text) # .text 可以获取a标签下的文本内容
soup1 = soup.find('div',class_="data__cont")
music_name1 = soup1.find('div',class_='data__name').text.strip('\n')
这个标签只有一个文本信息
music_name2 = soup1.find('div',class_='data__name').find('h1').text
music_name3 = soup1.find('div',class_='data__name').find('h1').get('title')
get_text('title')也可以
singer_name = soup1.find('div',class_='data__singer').get('title').replace(' / ','/')
print(singer_name + '-' + music_name1)
创建爬虫,分析目标网页内容,可以通过xpath方法,或者Css选择器的方法。
以下介绍常用的Css选择器使用方法
表达式 说明
* 选择所有节点
container 选择id为container的节点元素
.container 选取所有class包含container的节点元素
div # container > ul 选取id为container的div节点下面的第一个ul子元素
li a 选取li元素下面所有的a节点元素
ul + p 选择ul后面的第一个p元素
ul ~ p 选取与ul相邻的所有p元素
li:nth-child(3) 选取第三个li元素
tr:nth-child(2n) 选取偶数行
h1::text 伪类选择器,获取 h1 标签内的文本
a::attr(href) 伪类选择器,获取a连接href属性值 《《《《
a[title] 选取所有具有 title属性的a元素
a[href=“http://51xiudao.cn”] 选取所有href属性为51xiudao.cn值得a元素
a[href*=”51xiudao”] 选取所有href属性包含51xiudao的a元素
a[href^=”http”] 选取所有href以http开头的a元素
a[href$=”.jpg”] 选取所有href以 .jpg 结尾的a元素
以上三项中 * ^ $ 涉及到正则表达式的相关内容
input[type=radio]:checked 选择宣州的radio元素
div:not(#container) 选择所有id不等于container的div元素
.abc.def css中用两个class定位一个元素 例如< div class=”abc def” >xxx< / div>
注意:
解析方法一
import parsel
selector = parsel.Selector(response.text)
title = selector.css('div.data__name h1::attr(title)').extract()[0]
解析方法二
import scrapy
selector = scrapy.Selector(text=res.text)
title = selector.css('div.data__name h1::attr(title)').extract()[0]
item['title']=response.xpath('//ul[@class="bigimg"]/li/a[1]/@title').getall()
parsel模块,css语法
路径加上::attr 或者::text
末尾需要加入.extract()或者.getall()方法, scrapy解析的内容,不管是xpath,还是selector都要添加
.extract() 返回选中内容的Unicode字符串。
.extract_first() 选择第一个,
.getall() 获取所有元素节点
.get() 获取单个元素节点
css
1.不能使用相同属性的内容(一个class的属性含有多个同类型的数据),只使用一个
2.选择指定的子节点也需要使用:nth-child(n)
3.最开始的路径需要确定哪一个标签
本质 上将源代码页面,转换成Html节点。(即会默认执行javascript)
注意: class="xxx", 类名需要写全,否则无效
nodename 选取此节点的所有子节点。
/ 从根节点选取。
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置。 (//双斜杠代表所有)
. 选取当前节点。
.. 选取当前节点的父节点。
@ 选取属性。
* 匹配任何元素节点。 //* 选取文档中的所有元素。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。 //title[@*] 选取所有带有属性的 title 元素。
text() 匹配文本
tr.xpath('td[1]/text()').get() , 选取td[1]下的文本
注意:
解析方法一:parsel模块
import parsel
selector = parsel.Selector(response.text)
trs = selector.xpath('//table[@class="table table-bordered table-striped"]/tbody/tr')[0]
title = trs.xpath('td[2]/text()').get()
get() :获取单独的一个节点数据,否则获取的是一个节点对象
注意:这是[ ] 里面的起始值是1,路径不能以 / 斜杠结尾
解析方法二:etree模块
from lxml import etree
html = etree.HTML(music_res.text)
music_name = html.xpath('//div[@class="data__name"]/h1/@title')[0]
lxml模块 xpath语法
singer_name = html.xpath('//div[@class="data__singer"]/@title')[0]
路径加上@XXX 或者text()
另一种xpath语法是在末尾加上.text
实例:
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取根元素 bookstore。
注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position()<3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。 title[@lang] 选取所有拥有名为 lang 的属性的 title title[@lang="eng" ] 选取所有 元素,且这些元素拥有值为 eng 的 属性。 book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。
</3]>
jsonpath操作符:
操作 说明
$ 查询根元素。这将启动所有路径表达式。
@ 当前节点由过滤谓词处理。
* 通配符,必要时可用任何地方的名称或数字。
.. 深层扫描。 必要时在任何地方可以使用名称。
.<name> 点,表示子节点
['<name>' (, '<name>') 括号表示子项
[<number> (, <number>)] 数组索引或索引
[start:end] 数组切片操作
[?(<expression>)] 过滤表达式。 表达式必须求值为一个布尔值。
</expression></number></number></name></name></name>
注意:
与css,xpath选择器不同,jsonpath处理的只是json格式下的字典数据。
json_text = res.json()
authors = jsonpath.jsonpath(json_text,'$..author')
json_text必须放在前面
将文本转换成json对象(必须是双引号)
data = json.loads(res.text) # data = res.json()
picturl_urls = jsonpath.jsonpath(data,'$..value.0.url')
titles = jsonpath.jsonpath(data,'$..1.value')
字符串转换成json对象(可能无效)
data = json.loads(json.dumps(res[0]), strict=False)
正则匹配(建议)
## 解析json数据
def re_json(text,pre,now,next):
return re.findall (f'"{pre}".+?"{now}":"(.+?)".+?"{next}"', text)
实例
$..author 获取所有json中所有author的值
$.store.* 所有的东西,书籍和自行车
$.store..price 获取json中store下所有price的值
$..book.length() 获取json中book数组的长度
$.store.book[*].author 获取json中store下book下的所有author值
$..book[2] 获取json中book数组的第3个值
$..book[-2] 倒数的第二本书
$..book[0,1] 前两本书
$..book[:2] 从索引0(包括)到索引2(排除)的所有图书
$..book[1:2] 从索引1(包括)到索引2(排除)的所有图书
$..book[-2:] 获取json中book数组的最后两个值
$..book[2:] 获取json中book数组的第3个到最后一个的区间值
$..book[?(@.isbn)] 获取json中book数组中包含isbn的所有值
$.store.book[?(@.price < 10)] 获取json中book数组中price<10的所有值 $..book[?(@.price <="$['expensive'])]" 获取json中book数组中price<="expensive的所有值" $..book[?(@.author="~" .*rees i)] 获取json中book数组中的作者以rees结尾的所有值(rees不区分大小写) $..* 逐层列出json中的所有值,层级由外到内 code></10的所有值>
import requests
import parsel
import re
import concurrent.futures
import os
多线程爬虫
1. 引入concurrent.futures模块
2. 设置线程 executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
for page in range(0, 201):
url = f'https://www.fabiaoqing.com/biaoqing/lists/page/{page}.html'
3.提交数据 executor.submit(main, url)
4.关闭线程 executor.shutdown()
def get_response(html_url):
"""模拟浏览器请求网址,获得网页源代码"""
headers = {
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.138 Safari/537.36'
}
response = requests.get(url=html_url, headers=headers)
return response
def change_title(title):
"""正则匹配特殊字符标题"""
pattern = re.compile(r"[\/\\\:\*\?\"\<\>\|]") # '/ \ | < > : * ? " '
new_title = re.sub(pattern, "_", title) # 替换为下划线
return new_title
def save(img_url, title):
"""保存表情到本地文件"""
img_content = get_response(img_url).content
path = 'img\\' + title
with open(path, mode='wb') as f:
f.write(img_content)
print(title)
def main(html_url):
"""主函数"""
response = get_response(html_url)
selector = parsel.Selector(response.text)
divs = selector.css('.tagbqppdiv')
for div in divs:
img_url = div.css('a img::attr(data-original)').get()
tail = img_url.split('.')[-1]
title = div.css('a img::attr(title)').get()
# comment = comments[0] if len(comments) != 0 else "空"
if len(title)> 15:
title = title.split(' ')[0]
if len(title) > 15:
title = title[:15]
new_title = change_title(title) + '.' + tail
save(img_url, new_title)
def down_directory():
path = 'img\\' # ./img getcwd()+/img
os.makedirs(path,exist_ok=True)
if __name__ == '__main__':
down_directory()
executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
for page in range(0, 201):
print(f'第{page+1}页正在爬取...')
url = f'https://www.fabiaoqing.com/biaoqing/lists/page/{page}.html'
executor.submit(main, url)
executor.shutdown()
多线程与多进程的比较
import concurrent.futures
import time
#
def hello(data):
time.sleep(2)
print('time is ',data)
#
if __name__=='__main__':
executor = concurrent.futures.ThreadPoolExecutor(max_workers=5)
for i in range(0, 20):
executor.submit(hello,i) # 多线程进行多任务
executor.shutdown()
#
from multiprocessing import Pool
import time
def hello(data):
time.sleep (2)
print ('time is ', data)
if __name__ == '__main__':
pool = Pool(processes=5)
i = [f'{data}' for data in range(0,20)]
pool.map(hello,i) # 多进程进行多个程序
</\>
爬取站酷Zcool网站图片
import os
import re
import asyncio
import aiohttp
import requests
import time
import pprint
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
}
if not os.path.exists('./站酷Zcool图片'):
os.mkdir('./站酷Zcool图片/')
async def get_content(link):
async with aiohttp.ClientSession() as session:
try:
response = await session.get(link)
content = await response.read()
return content
except asyncio.exceptions.TimeoutError:
print('timeout')
pass
def get_content_2(link):
response = requests.get(link,headers=headers).text
return response
async def downloader(img):
content = await get_content(img[1])
# title = img.split('/')[-1]
with open('./站酷Zcool图片/'+str(img[0])+'.jpg','wb') as f:
f.write(content)
print('下载成功',img[0],img[1])
def run():
start = time.time()
base_url = 'https://www.zcool.com.cn/work/content/show?p=2&objectId=6455837' #https://www.zcool.com.cn/work/content/show?p=2&objectId=6455837
r = requests.get(base_url,headers=headers)
image = r.json() # image = json.loads(r.text)
ima = image['data']['allImageList']
# 创建协程对象
loop = asyncio.get_event_loop()
# 指定协和运行任务
# 因为run函数不是一个异步函数,所以我们需要使用ensure_future去调用downloader # 传入的参数是一个元组
tasks = [asyncio.ensure_future(downloader((i,image['url']))) for i,image in enumerate(ima)]
loop.run_until_complete(asyncio.wait(tasks))
end = time.time() # 获取时间戳
print('共运行了'+str(end-start)+'秒')
if __name__=='__main__':
run()
#
import os
import re
import asyncio
import aiohttp
import requests
import time
import pprint
#
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
}
def down_directory():
if not os.path.exists('./站酷Zcool图片'):
os.mkdir('./站酷Zcool图片/')
#
async def get_content(link):
async with aiohttp.ClientSession() as session:
response = await session.get(link)
content = await response.read()
return content
# def get_content_2(link):
# response = requests.get(link,headers=headers).text
# return response
#
async def downloader(img):
content = await get_content(img)
title = img.split('/')[-1]
with open('./站酷Zcool图片/'+title,'wb') as f:
f.write(content)
print('下载成功',img)
#
def run(url):
start = time.time()
res = requests.get(url=url,headers=headers)
before_url = re.findall('data-objid="(.*?)"',res.text)[0] # data-objid = "6455837"
base_url = 'https://www.zcool.com.cn/work/content/show?p=2&objectId='+before_url #https://www.zcool.com.cn/work/content/show?p=2&objectId=6455837
r = requests.get(base_url,headers=headers)
image = r.json() # image = json.loads(r.text)
# pprint.pprint(image)
# image_list = []
# ima = image['data']['allImageList']
# for i in range(len(ima)):
# image_list.append(ima[i]['url'])
# print(image_list)
ima = image['data']['allImageList']
# 创建协程对象
loop = asyncio.get_event_loop()
# 指定协和运行任务
# 因为run函数不是一个异步函数,所以我们需要使用ensure_future去调用downloader
tasks = [asyncio.ensure_future(downloader(image['url'])) for i,image in enumerate(ima)]
loop.run_until_complete(asyncio.wait(tasks))
end = time.time() # 获取时间戳
print('共运行了'+str(end-start)+'秒')
#
if __name__=='__main__':
down_directory()
url = 'https://www.zcool.com.cn/work/ZMjU4MjMzNDg=.html'
run(url)
万能爬虫,headers
import requests
import random
user_agent = [
"Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows; U; Windows NT 6.1; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
"Mozilla/5.0 (Windows NT 10.0; WOW64; rv:38.0) Gecko/20100101 Firefox/38.0",
"Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; .NET4.0C; .NET4.0E; .NET CLR 2.0.50727; .NET CLR 3.0.30729; .NET CLR 3.5.30729; InfoPath.3; rv:11.0) like Gecko",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)",
"Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)",
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1",
"Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
"Opera/9.80 (Windows NT 6.1; U; en) Presto/2.8.131 Version/11.11",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Maxthon 2.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; TencentTraveler 4.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; The World)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SE 2.X MetaSr 1.0; SE 2.X MetaSr 1.0; .NET CLR 2.0.50727; SE 2.X MetaSr 1.0)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Avant Browser)",
"Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)",
"Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (iPod; U; CPU iPhone OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (iPad; U; CPU OS 4_3_3 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8J2 Safari/6533.18.5",
"Mozilla/5.0 (Linux; U; Android 2.3.7; en-us; Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"MQQBrowser/26 Mozilla/5.0 (Linux; U; Android 2.3.7; zh-cn; MB200 Build/GRJ22; CyanogenMod-7) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
"Opera/9.80 (Android 2.3.4; Linux; Opera Mobi/build-1107180945; U; en-GB) Presto/2.8.149 Version/11.10",
"Mozilla/5.0 (Linux; U; Android 3.0; en-us; Xoom Build/HRI39) AppleWebKit/534.13 (KHTML, like Gecko) Version/4.0 Safari/534.13",
"Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, like Gecko) Version/6.0.0.337 Mobile Safari/534.1+",
"Mozilla/5.0 (hp-tablet; Linux; hpwOS/3.0.0; U; en-US) AppleWebKit/534.6 (KHTML, like Gecko) wOSBrowser/233.70 Safari/534.6 TouchPad/1.0",
"Mozilla/5.0 (SymbianOS/9.4; Series60/5.0 NokiaN97-1/20.0.019; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.1.18124",
"Mozilla/5.0 (compatible; MSIE 9.0; Windows Phone OS 7.5; Trident/5.0; IEMobile/9.0; HTC; Titan)",
"UCWEB7.0.2.37/28/999",
"NOKIA5700/ UCWEB7.0.2.37/28/999",
"Openwave/ UCWEB7.0.2.37/28/999",
"Mozilla/4.0 (compatible; MSIE 6.0; ) Opera/UCWEB7.0.2.37/28/999",
]
#request 请求头部、由于此脚本请求不同的网页header信息不一致所以未设置全局变量
#解析woff字体库的数字类型
headers1 = {'User-Agent': random.choice(user_agent), # 随机选取头部代理,防止被屏蔽
'Connection': "keep-alive",
'Host': "www.dianping.com",
'referer': 'http://www.dianping.com/',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
}
headers2 = {'User-Agent': random.choice(user_agent), # 随机选取头部代理,防止被屏蔽
'Connection': "keep-alive",
'Host': "s3plus.meituan.net",
'referer': 'http://www.dianping.com/',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
}
headers3 = {'User-Agent': random.choice(user_agent), # 随机选取头部代理,防止被屏蔽
'Connection': "keep-alive",
'Host': "s3plus.meituan.net",
'referer': 'http://www.dianping.com/',
'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3',
}
浅谈网页referer的作用以及反爬虫的解决方法
  我们知道,referer的作用就是记录你在访问一个目标网站时,在访问前你的原网站的地址,比如用Chrome从知乎的某个板块到另外一个,那么你在的这个网站就是原网站,按F12,选中Network选项,从页面内进入一个网站,可以从这个网站的header即头信息中看到referer就是原来的那个网站。
  由于referer是请求网页中,也就是发起HTTP请求中header的一部分,所以可以用来做网页的图片防盗链!比如一个网页的图,想用Python下载到自己的电脑里,用urllib.request或者requests第三方库访问图片时爬不下来,这是因为Python提交request申请的时候,就类似于在浏览器中的空地址栏里键入这个网页然后访问,
没有referer,这时网站的设置比如是要求有referer,且referer的网站必须是你进来之前的网站,也就是这个图片的主页。
  既然要求你传入图片主页面的referer,在构造header的时候,传入Referer参数(注意R要大写)(Request Headers的referer),它的值为与这个图片链接相关的网站,或者这个图片链接地址的原网站就可以了,下面是代码。
  
1.文件读取
f.read()读取所有数据(文件很小,否则需要调用f.read(size)),返回的是一个字符串。
f.readline()读取一行数据
f.readlines()读取所有数据,返回一个列表。
open方法(f.open)需要使用f.close()关闭文件,也可能会出现IO异常。
with语句(with open(path,'r') as f:)不用close()
一般文本文件不用'b',含中文的文件需要使用encoding='utf-8'
2.序列化与反序列化
序列化就是把内存中的变量转换为可存储或可传输的过程
一般使用pickle模块,pickle.dump(d,f)
反序列化就是把变量内容从序列化的对象重新读取到内存,称为反序列化
一般使用pickle模块,d = pickle.load(f)
3.web前端基础
W3C标准 即万维网联盟
网页主要由3部分组成:结构,表现,和行为
结构化标准语言主要包括XHTML和XML,表现标准语言主要包括CSS,行为标准主要包括对象模型(如W3C DOM),ECMAScript等
转义字符 \ \t, \n, \. , \\
4.爬虫实战
r.content 返回的是字节形式,r.text返回的是文本形式,r.encoding返回的是http头猜测的网页编码格式
Requests提供了解决方案,可以自行设置编码格式,r.encoding=utf-8设置成UTF-8之后,“new text-->”的内容就不会出现乱码。
但是这种手动的方式略显笨拙,下面提供一种更加简便的方式: chardet,这是一个非常优秀的字符串/文件编码检测模块。安装方式如下:
pip install chardet 安装完成后,使用chardet.detect()返回字典,其中 confidence是检测精确度,encoding是编码形式。
示例如下: import requests
r = requests.get('http://www.baidu.com')
print chardet.detect(r.content)
r.encoding = chardet.detect(r.content)['encoding ']
print(r.text)
直接将chardet 探测到的编码,赋给r.encoding实现解码,r.text输出就不会有乱码了。除了上面那种直接获取全部响应的方式,还有一种流模式,示例如下:
import requests
r = requests.get('http://www.baidu.com',stream=True)
print(r.raw.read(10)
设置stream=True标志位,使响应以字节流方式进行读取, r.raw.read 函数指定读取的字节数。
chrome + chromedriver
把chromedriver放在chrome同级目录下,并向环境变量添加chromedriver路径
http://npm.taobao.org/mirrors/chromedriver/ 下载地址
from selenium import webdriver
driver = webdriver.Chrome() # 创建一个浏览器驱动对象
driver的方法
1. .get("xxx") 方法进入网页
2. .close() 关闭窗口
3. .implicitly_wait(n) 隐式等待n秒
4. .find_element_by_id("Xxxx") 获取元素信息
5. .page_source 获取网页源码
6. .execute_script('window.scrollTo(0,document.body.scrollHeight)')
7. document.documentElement.scrollTop = document.documentElement.scrollHeight * %f
element = driver.find_element_by_id("xxx") 获取表单框截图
element.screenshot(filename)
y_element = driver.find_element_by_id('xxx') 获取验证码截图
y_element.location['x/y']
y_element.size['x/y']
1.click() 点击
2.send_keys('xxxx') 输入信息
find_element_by_id
find_element_by_name
find_element_by_xpath 使用xpath读法进行获取
find_element_by_link_text
find_element_by_partial_link_text
find_element_by_tag_name
find_element_by_class_name
find_element_by_css_selector 使用css选择器获取数据
find_elements_by_id
find_elements_by_name
find_elements_by_xpath
find_elements_by_link_text
find_elements_by_partial_link_text
find_elements_by_tag_name
find_elements_by_class_name
find_elements_by_css_selector
使用方法:
1..text方法 获取文本信息(xpath是在路径后加/text())
2..get_attribute('xxx') 获取标签属性
3. 只有find_elements获取的结果才可以进行迭代。
新版本的选择器
from selenium.webdriver.common.by import By
div_list = driver.find_element(By.XPATH, "/html/body/div/div[2]/div[1]/div")
driver.find_element(By.NAME, "NAME")
driver.find_element(By.CLASS_NAME, "CLASS_NAME")
driver.find_element(By.ID, "ID")
driver.find_element(By.XPATH, "XPATH")
driver.find_elements(By.XPATH, "XPATH")
例4:爬取英雄联盟的图片 -- selenium模拟浏览器+ssl证书
-*- coding:utf-8 -*-
import os
from urllib import request
from selenium import webdriver
import ssl # 证书
import time
'''
网站串:http 相对不安全的网站
https 相对安全,需要证书支验证当前请求是否合格
'''
ssl._create_default_https_context = ssl._create_unverified_context
def download_dir():
if not os.path.exists('./皮肤/'):
os.mkdir('./皮肤/')
def get_images():
hero = []
# 创建一个浏览器驱动对象
driver = webdriver.Chrome()
driver.get('https://lol.qq.com/data/info-heros.shtml')
time.sleep(1)
driver.execute_script('window.scrollTo(0,document.body.scrollHeight)')
infos = driver.find_element_by_id('jSearchHeroDiv')
links = infos.find_elements_by_css_selector('li>a')
for link in links:
urls = link.get_attribute('href')
hero.append(urls.split())
for i in range(len(hero)):
driver.get(hero[i][0])
time.sleep(2)
# 控制浏览器下滑到指定位置
driver.execute_script('window.scrollTo(100,800)')
time.sleep(0.5)
driver.find_element_by_css_selector('#skinNAV').find_elements_by_css_selector('li a')[1].click()
skins = driver.find_element_by_css_selector('#skinBG').find_elements_by_css_selector('li')
for i,skin in enumerate(skins):
img_title = skin.get_attribute('title')
img_url = skin.find_element_by_css_selector('img').get_attribute('src')
print(img_url,img_title)
try:
request.urlretrieve (img_url, './皮肤/' + img_title + '.jpg')
print(f'{img_title}保存成功')
except Exception:
print('保存失败')
pass
if __name__=='__main__':
download_dir()
get_images()
例7:爬取短租小猪的所有网页的房租信息(chomedriver模拟人工操作,进行数据的提取)
from selenium import webdriver
import time
def down_data(info,price,content,score,img1,img2,num): # 保存数据
fp = open('c://Users/Icy-yun/Desktop/短租小猪.txt','a+')
try:
fp.write('='*5 + info + '='*5 + '\n') # 防止出现异常
except:
fp.write('名字有误!'+'\n')
print('名字有误!'+info)
fp.write('环境:'+content + '\n')
fp.write('价格:'+price)
fp.write(' 评分:' + score + '\n')
try:
fp.write('居住环境图片url:')
fp.write(img1+'\n')
fp.write('房东图片url:')
fp.write(img2+'\n')
except:
fp.write('无'+'\n')
print('缺少url')
fp.write(f'------------{num}------------\n')
fp.close()
def next_page(): # 对python信息进行翻页
num = 1
while num<=13: # 进行翻页 driver.get(f'https: bj.xiaozhu.com search-duanzufang-p{num}-0 ') 经过裁剪后的url driver.implicitly_wait(10) 隐式等待10s,可以根据网页的加载速度而减少时间,超时会出现异常 drop_down() 调用下拉滑块函数 get_product() # 调用信息采集函数 print('="*10,f" 第{num}页信息已经采集完毕','="*10," \n') num +="1" def drop_down(): 下拉滑块 for x in range(1,11,2): time.sleep(0.5) j="x/10" 按照百分比拉动滑块 js="document.documentElement.scrollTop = document.documentElement.scrollHeight * %f" %j driver.execute_script(js) get_product(): 信息采集 lis="driver.find_elements_by_xpath('//ul[@class="pic_list" clearfix list_code"] li') 注意联系每行的第一个元素 li lis: info="li.find_element_by_xpath('.//div/div/a/span[@class="result_title" hiddentxt"]').text price="li.find_element_by_xpath" ('. div span[@class="result_price" ]').text content="li.find_element_by_xpath('.//div/div/em[@class="hiddenTxt"]').text.split('-')[0]" score="li.find_element_by_xpath('.//div/div/em[@class="hiddenTxt"]').text.split('-')[1]" img1="li.find_element_by_xpath('.//a/img[@class="lodgeunitpic"]').get_attribute('src')" img2="li.find_element_by_xpath('.//div/span/a/img[@class="landlordimage"]').get_attribute('src')" print (info,price,content,score,img1,img2) down_data(info,price,content,score,img1,img2,num) print(f'--已经保存第{num}条数据!') if __name__="=" '__main__': 主程序 driver="webdriver.Chrome()" driver.get('https: 正在浏览网页数据','="*5)
next_page()
print(" ='*5,'数据已经保存','="*5)
</code></pre><pre><code># 例1:qq音乐收藏歌曲 + 各种解析方法
-*- coding:utf-8 -*-
import requests
import re
from lxml import etree
import parsel
from bs4 import BeautifulSoup
headers = {
" cookie': 'pgv_pvid="7816360320;" ts_refer="www.baidu.com/link;" ts_uid="715288657;" rk="AWrVxhWv2R;" ptcz="aeecf60024480f5a2f998c86865e2219e42d1eee4bdf52dbdd462e7e007503db;" euin="ow-l7wEl7e6P7z**;" psrf_qqunionid=";" psrf_qqrefresh_token="5C7BA00E03C8600F9563367642F26A40;" psrf_qqaccess_token="1909A64E8D690EDFC1CF55080A9464C8;" psrf_qqopenid="1D90998FC112B52BE4601A83300E63B2;" tmelogintype="2;" uin="2276974147;" yq_index="0;" yqq_stat="0;" pgv_info="ssid=s6073666250;" useraction="1;" _qpsvr_localtk="0.640678577047278;" psrf_access_token_expiresat="1621301506;" psrf_musickey_createtime="1613525506;" qm_keyst="Q_H_L_28WSi060eei8rmEz-RPuZsZ90y9-EJrOT0dnjTgeUfKItbC3Aelz9aiUVS287U1;" qqmusic_key="Q_H_L_28WSi060eei8rmEz-RPuZsZ90y9-EJrOT0dnjTgeUfKItbC3Aelz9aiUVS287U1;" ts_last="y.qq.com/portal/profile.html'," 'origin': 'https: y.qq.com', 'referer': y.qq.com ', 'sec-fetch-dest': 'empty', 'sec-fetch-mode': 'cors', 'sec-fetch-site': 'same-site', 'user-agent': 'mozilla 5.0 (windows nt 10.0; win64; x64) applewebkit 537.36 (khtml, like gecko) chrome 86.0.4240.111 safari 537.36', } param="{" 'dirid': '201', 'dirinfo': '1', 'g_tk_new_20200303': '28041333', 'g_tk': 'loginuin': '2276974147', 'hostuin': '0', 'format': 'json', 'incharset': 'utf8', 'outcharset': 'utf-8', 'notice': 'platform': 'yqq.json', 'neednewcode': header="{" 537.36' url="https://c.y.qq.com/splcloud/fcgi-bin/fcg_musiclist_getmyfav.fcg?dirid=201&dirinfo=1&g_tk_new_20200303=28041333&g_tk=28041333&loginUin=2276974147&hostUin=0&format=json&inCharset=utf8&outCharset=utf-8¬ice=0&platform=yqq.json&needNewCode=0" res="requests.get(url=url,headers=headers)" html="res.json()" https: n yqq song 002nkern2lnvi4.html print(html) music_ids="html['mapmid']" music_urls="[f'https://y.qq.com/n/yqq/song/{id}.html'" id music_ids] i,music_url enumerate(music_urls): print(f'第{i+1}首歌曲url:',music_url) try: music_res="requests.get(music_url,headers=header)" music_res.encoding="utf-8" 一、re模块,正则表达式 music_name="re.findall('"songtype":0,"songname":"(.*?)","songtitle":',music_res.text)[0]" singer_name="re.findall('"mid":".*?","singername":"(.*?)","singerid"',music_res.text)[0]" 功能可能需要加上re.s 二、lxml模块(xpath语法,selector语法) lxml模块 xpath语法 路径加上@xxx 或者text() 另一种xpath语法是在末尾加上.text selector="parsel.Selector(music_res.text)" h1::attr(title)').extract()[0] parsel模块,css语法 路径加上::attr 或者::text 末尾需要加入.extract()或者.getall()方法 三、beautifulsoup.bs4模块 find返回第一个标签,find_all返回一个列表,包含所有标签 find和find_all 有.get('xxx')方法 .get_text('xxx')方法 .text方法 soup="BeautifulSoup(music_res.text,'lxml')" html.parser或者'lxml' .printtify()格式化打印 select有.get_text()方法 print(soup.title) soup.title.string 获得标题 soup.title获得标题标签(文本加标签<>)
# print(soup.a['href']) # soup.a['href'] 获取第一个a标签的href属性
# print(soup.find('a').get('href')) # soup.find('a').get('href') 获取第一个a标签的href属性
# print(soup.find_all('a')) # find_all['a'] 可以获取所有a标签,返回一个列表。
# for s in soup.find_all('a'): # .get('href') 可以获取a标签下的href属性
# print(s.get_text('href')) # .get_text('href')可以获取a标签href属性所在行的文本内容
# print(s.text) # .text 可以获取a标签下的文本内容
soup1 = soup.find('div',class_="data__cont")
music_name1 = soup1.find('div',class_='data__name').text.strip('\n')
# 这个标签只有一个文本信息
# music_name2 = soup1.find('div',class_='data__name').find('h1').text
# music_name3 = soup1.find('div',class_='data__name').find('h1').get('title')
# get_text('title')也可以
singer_name = soup1.find('div',class_='data__singer').get('title').replace(' / ','/')
print(singer_name + '-' + music_name1)
except:
print('error')
pass
</=13:>
scrapy Engine scrapy框架
spider 蜘蛛(爬虫)
ItemPipleline 项目管道
Downloader 下载器
Scheduler 调度程序
字典生成式:
dict = {item:price for item,price in zip(items,prices)}
def func(*args){ } 可变参数,args变成一个元组, func(1,2)
def func(**dicts){ } 按键值传入实参,dicts是一个字典。func(a=1,b=2)
scrapy 展示所有scrapy框架命令
scrapy bench 测试scrapy
exit() 退出编辑器
scrapy shell 对应网址 验证scrapy框架爬虫的xpath语句
(第一: title = xpath(....) 第二: title)
注意:
1.只有在项目下的“scrapy.cfg”同级,才可以执行有效的命令
2.如果scrapy没有添加环境变量, 可以采用命令添加前缀的方法 python -m scrapy xxxx
1.建立爬虫项目
命令:cd : c:\scrapy
scrapy startproject scrapy_demo0
2.建立爬虫文件
命令:cd scrapy_demo0
scrapy genspider demo_spider quotes.toscrape.com
(或者scrapy genspider -t basic demo_spider "quotes.toscrape.com")
(或者scrapy genspider -t crawl demo_spider "quotes.toscrape.com")
3.运行爬虫文件
命令: scrapy crawl demo_spider
在spiders/xxxSpiner文件
1.新建的xiaozhuspider文件里的parse是默认的函数,用于解析返回的结果
2.每个xpath语句后都要添加一个.extract() 或.getall(), 用于提取数据, 注意get()用于提取单个元素
3.items 项目中 把需要获取的项目信息 写在items的默认函数里 name=scrapy.Field()
4.xxSpider爬虫文件中引入items项目文件 from ..items import DouyuItem (..表示当前目录的上一级目录)
(1)、初始化爬虫数据
类的成员 start_urls 列表 、base_url 有关url参数 、offset 参数、自定义成员urls
类的方法 parse(self, response)
初始化属性值:
start_urls = [base_url+str(offset)]
start_urls = [f'https://ys.mihoyo.com/main/character/{page}?char=0' for page in ('mondstadt','liyue')]
start_urls = [f'https://ys.mihoyo.com/main/character/{page}?char=0' for page in urls]
(2)、解析数据
json格式的数据 data_list=json.loads(response.body)['data']
xpath语法 picture_urls = response.xpath ('//ul[@class="list-group"]/li/div/div/a/img/@data-original').extract() (不需要使用 html=etree.HTML(res.text))
re 模块 titles = re.findall ('{title:"(.*?)",icon', response.text)
(3)、往items文件写入数据
def parse(self,response):
for data in data_list:
item=DouyuItem()
item['name']=data['nickname'].encode('utf-8')
item['vertical_src']=data['vertical_src']
yield item
或者
for div in divs:
title=div.xpath('./div/p[1]/a/text()').get()
title_url=div.xpath('./div/p[1]/a/@href').get()
info=div.xpath('./div/p[2]/a/text()').get()
img_url=div.xpath('./a/img/@src').get()
item = QdEnglishItem(title=title,title_url=title_url,info=info,img_url=img_url)
yield item
(4)、也可以在parse函数中进行翻页操作
def parse(self,response):
self.offset += 20 #翻页
url = self.base_url+str(self.offset)
yield scrapy.Request(url,callback=self.parse,dont_filter=True)
0.pipelines管道下载文件中引入 文件模块 imort os
1.(和 图片模块from scrapy.pipelines.images import ImagesPipeline)(或者import csv)
2. 该文件不用引入items项目,默认使用items里面的数据
(1)、类的成员 自定义(可以直接使用item['xxx'],不用引入模块)
类的方法 process_item(self, item, spider),
item_completed(self,result,item,info)
__init__(self)
close_file(self)
(2)、获取每张图片信息
def get_media_requests(self, item, info):
image_link=item['vertical_src']
yield scrapy.Request(image_link) # 这里因为需要再次获取图片信息
(3)、初始化
def __init__(self):
self.f=open('data.csv',mode='a',encoding='utf-8',newline='')
self.csv_write=csv.DictWriter(self.f,fieldnames=['title','title_url','info','img_url'])
self.csv_write.writeheader()
(4)、下载文件
def item_completed(self, result, item, info):
path='C:/Users/Icy-yun/Desktop/douyu/'
f result[0][0]==True:
os.rename(path+result[0][1]['path'],path+str((item['name']).decode()+'.jpg'))
return item
或者
def process_item(self, item, spider):
self.csv_write.writerow(dict(item))# item是一个数据字典
return item
def close_file(self):
self.f.close()
settings设置文件中
(1).把setting文件夹里面的robots协议修改一下,ROBOTSTXT_OBEY = False
(2).使用了管道下载需要打开
ITEM_PIPELINES = {
'douyu.pipelines.DouyuPipeline': 300,
}
(3).如果数据太多可以调整下载延迟时间DOWNLOAD_DELAY = 3
(4).如果需要爬虫可以正常运行,也可以添加请求头
DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'
}
1.数据库设计为utf-8的字符集 、 utf8_general_ci的排序规则
2.设计表时注意主键唯一,否则会出现数据无法插入的情况(也可以不设置主键)
3.编写代码时一定要注意charset = 'utf8' 没有‘-’
Esc键 定位到最后一行
Ctrl + C 停止爬取
1.pipelines管道下载文件,引入pymysql模块
def process_item(self, item, spider):
# 1.建立连接,utf8编码
conn = pymysql.connect(host="127.0.0.1",user="root",passwd="xxx",db="dangdang",charset="utf8")
# 2.拿到游标
cursor = conn.cursor ()
for title,link,comment in zip(item["title"],item["link"],item["comment"]):
sql = "insert into books(title,link,comment) values(%s,%s,%s)"
# 3.执行SQL语句
cursor.execute(sql,(title,link,comment))
# 4.向数据库提交
conn.commit()
# 5.关闭游标,数据库
cursor.close()
conn.close()
return item
scrapy_demo0/scrapy_demo0/items定义变量文件
import scrapy
class ScrapyDemo0Item(scrapy.Item):
# define the fields for your item here like:
content = scrapy.Field()
author = scrapy.Field()
tags = scrapy.Field()
scrapy_demo0/scrapy_demo0/pipelines管道下载文件
import os
class ScrapyDemo0Pipeline:
def __init__(self):
self.f=open (os.getcwd () + '/爬取数据.txt', 'a+')
def process_item(self, item, spider):
self.f.write (f'作者:{item["author"][0]}\n')
self.f.write (f'标签:{item["tags"][0]}\n')
self.f.write (f'名言:{item["content"][0].strip("“").strip("”")}\n\n')
return item
def close_file(self):
self.f.close()
scrapy_demo0/scrapy_demo0/settings 配置文件
Scrapy settings for scrapy_demo0 project
#
For simplicity, this file contains only settings considered important or
commonly used. You can find more settings consulting the documentation:
#
https://docs.scrapy.org/en/latest/topics/settings.html
https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
https://docs.scrapy.org/en/latest/topics/spider-middleware.html
BOT_NAME = 'scrapy_demo0'
SPIDER_MODULES = ['scrapy_demo0.spiders']
NEWSPIDER_MODULE = 'scrapy_demo0.spiders'
Crawl responsibly by identifying yourself (and your website) on the user-agent
#USER_AGENT = 'scrapy_demo0 (+http://www.yourdomain.com)'
Obey robots.txt rules
ROBOTSTXT_OBEY = False
Configure maximum concurrent requests performed by Scrapy (default: 16)
#CONCURRENT_REQUESTS = 32
Configure a delay for requests for the same website (default: 0)
See https://docs.scrapy.org/en/latest/topics/settings.html#download-delay
See also autothrottle settings and docs
#DOWNLOAD_DELAY = 3
The download delay setting will honor only one of:
#CONCURRENT_REQUESTS_PER_DOMAIN = 16
#CONCURRENT_REQUESTS_PER_IP = 16
Disable cookies (enabled by default)
#COOKIES_ENABLED = False
Disable Telnet Console (enabled by default)
#TELNETCONSOLE_ENABLED = False
Override the default request headers:
#DEFAULT_REQUEST_HEADERS = {
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
'Accept-Language': 'en',
#}
Enable or disable spider middlewares
See https://docs.scrapy.org/en/latest/topics/spider-middleware.html
#SPIDER_MIDDLEWARES = {
'scrapy_demo0.middlewares.ScrapyDemo0SpiderMiddleware': 543,
#}
Enable or disable downloader middlewares
See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html
#DOWNLOADER_MIDDLEWARES = {
'scrapy_demo0.middlewares.ScrapyDemo0DownloaderMiddleware': 543,
#}
Enable or disable extensions
See https://docs.scrapy.org/en/latest/topics/extensions.html
#EXTENSIONS = {
'scrapy.extensions.telnet.TelnetConsole': None,
#}
Configure item pipelines
See https://docs.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
'scrapy_demo0.pipelines.ScrapyDemo0Pipeline': 300,
}
Enable and configure the AutoThrottle extension (disabled by default)
See https://docs.scrapy.org/en/latest/topics/autothrottle.html
#AUTOTHROTTLE_ENABLED = True
The initial download delay
#AUTOTHROTTLE_START_DELAY = 5
The maximum download delay to be set in case of high latencies
#AUTOTHROTTLE_MAX_DELAY = 60
The average number of requests Scrapy should be sending in parallel to
each remote server
#AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
Enable showing throttling stats for every response received:
#AUTOTHROTTLE_DEBUG = False
Enable and configure HTTP caching (disabled by default)
See https://docs.scrapy.org/en/latest/topics/downloader-middleware.html#httpcache-middleware-settings
#HTTPCACHE_ENABLED = True
#HTTPCACHE_EXPIRATION_SECS = 0
#HTTPCACHE_DIR = 'httpcache'
#HTTPCACHE_IGNORE_HTTP_CODES = []
#HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'
scrapy_demo0/scrapy_demo0/spiders/demo_spider爬虫文件
import scrapy
import os
from ..items import ScrapyDemo0Item
class DemoSpiderSpider(scrapy.Spider):
name = 'demo_spider'
allowed_domains = ['toscrape.com']
start_urls = [
'http://quotes.toscrape.com'
]
def init(self):
# 先清除原有的文件;
if os.path.exists (os.getcwd () + '/爬取数据.txt'):
os.remove (os.getcwd () + '/爬取数据.txt')
def parse(self, response):
# 采用scrapy的selector方法解析数据
for quote in response.css('div.quote'):
content = quote.css ('span.text::text').extract_first (),
author = quote.css ('span small::text').extract_first (),
tags = ','.join(quote.css ('div.tags a.tag::text').extract ()),
item = ScrapyDemo0Item(content=content,author=author,tags=tags)
yield item
next_page = response.css('li.next > a::attr(href)').extract_first()
print(next_page)
if next_page:
yield scrapy.Request(response.urljoin(next_page))
例3:爬取代理网站--chardet编码解析库+parsel库xpath语法+代理检测
'''
### 爬取云代理、快代理网站, 代理测试
'''
import requests
import parsel
import time
import chardet
请求头
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36'
}
从代理网站中解析数据
def parse_page(pre_url,pageCount):
proxy_list = []
num = 0
for page in range(1,pageCount):
time.sleep(0.5)
## 拼接完整的路径
url = pre_url+str(page)
print(f'====正在抓取第{page}页数据=====')
# 发送网络请求
res = requests.get(url=url,headers=headers) # <>表示的是一个对象
print(chardet.detect(res.content)) # chardet.detect(res.content) 可以检测编码格式
res.encoding = chardet.detect(res.content)['encoding'] # encoding是猜测编码格式
# print(res.text)
# res.encoding = 'gbk' # 这种方法需要进行调试,才知道是否网页是哪一种编码类型
'''
Requests提供了解决方案,可以自行设置编码格式,r.encoding=utf-8设置成UTF-8之后,“new text-->”的内容就不会出现乱码。
但是这种手动的方式略显笨拙,下面提供一种更加简便的方式: chardet,这是一个非常优秀的字符串/文件编码检测模块。安装方式如下:
pip install chardet 安装完成后,使用chardet.detect()返回字典,其中 confidence是检测精确度,encoding是编码形式
'''
selector = parsel.Selector(res.text) # css语法 # parsel模块封装了re、lxml、css模块
# trs1 = selector.css('table.table-striped tbody tr td:nth-child(1)::text').extract()
# trs2 = selector.css('table.table-striped tbody tr td:nth-child(2)::text').extract()
'''
使用parsel解析模块解析
css 1.不能使用相同属性的内容(一个class的属性含有多个同类型的数据),只使用一个
2.选择指定的子节点也需要使用:nth-child(n)
3.最开始的路径需要确定哪一个标签
xpath 1.需要使用get()来获取数据,否则获取的是一个对象
'''
## 两个网站的表格类似
### 云代理的内容
# trs = selector.xpath('//table[@class="table table-bordered table-striped"]/tbody/tr')
### 快代理的内容
trs = selector.xpath('//table[@class="table table-bordered table-striped"]/tbody/tr')
for tr in trs:
ip_type = tr.xpath('td[4]/text()').get()
ip_proxy = tr.xpath('td[1]/text()').get()
ip_port = tr.xpath('td[2]/text()').get()
proxies_dict ={
ip_type: ip_type + "://" + ip_proxy + ":" + ip_port,
}
proxy_list.append(proxies_dict)
print('保存成功:',proxies_dict)
num += 1
print('获取到的代理 ip数量:',num)
print('\n正在进行检测IP')
check_ip(proxy_list)
检测IP或使用代理IP访问网站
def check_ip(proxy_list,isTest=None,t_url=None,t_headers=None,t_params=None):
''' 检测代理ip的可用性'''
c_url = 'http://www.baidu.com/' ## 默认使用百度首页来测试ip的有效性
c_headers = headers
use_proxy = []
if isTest == None or isTest == True:
print('正在检测IP...')
else:
print('正在使用代理IP访问网页...')
if t_url != None: ## 外部url
c_url = t_url
if t_headers != None: ## 外部headers
c_headers = t_headers
for ip in proxy_list: # data ,param ### proxies值应该是一个字典
try: ### proxies = {'http':'http://123.456.75:00'}
if isTest == None or isTest == True: ### 测试IP有效性
ip_res = requests.get(url=c_url,headers=c_headers,proxies=ip,timeout=3)
if ip_res.status_code == 200:
use_proxy.append(ip)
print(f'当前代理ip:{ip}合格')
time.sleep(0.2)
else: ### 使用代理IP访问外部网页,代理IP不需要请求头
res = None
if t_params == None:
res = requests.get(url=c_url,proxies=ip,timeout=3)
else:
res = requests.get(url=c_url,params=t_params,proxies=ip,timeout=3)
print ('已经提取数据')
try:
code1 = chardet.detect (res.content)["encoding"] ### 双重编码来保证编码的正确性
code2 = res.apparent_encoding ### 但依然有很多网站有编码方面的防御措施
if code1 != None:
res.encoding = code1
else:
if code2 != None:
res.encoding = code2
else:
raise Exception ("chardet库和apparent_encoding编码都为None")
print (f'当前已经解码{res.encoding}')
except Exception as e:
print (f'当前编码已经设置为默认utf8编码格式,{e}')
res.encoding = 'utf8'
pass
if res.status_code == 200:
print('当前网页数据是'+res.text)
else:
print('请求网页数据失败,请重试')
except Exception as e:
if isTest == None or isTest == True:
print(f'当前代理ip:{ip}请求超时,检测不合格')
else:
print(f'当前无法使用代理IP访问当前网页{e}')
if isTest == None or isTest == True: ## 测试IP结果
if len(use_proxy)!=0:
print('\n正在列举可用IP:')
for i,proxy in enumerate(use_proxy):
print(f'第{i+1}个可用IP:{proxy}')
else:
print('抱歉!所有IP都不可用')
else: ## 代理IP访问网站的结果
print('使用代理IP访问网页结束')
if __name__=="__main__":
#### 云代理
# pre_url = 'http://www.ip3366.net/?stype=1&page='
# pageCount = 11
# parse_page(pre_url,pageCount)
#### 快代理
# pre_url = 'https://www.kuaidaili.com/free/inha/'
# pageCount = 11
# parse_page(pre_url,pageCount)
#### 测试代理IP的有效性
proxies_list = []
proxies_items = {'HTTP': 'HTTP://59.55.164.25:3256'}
proxies_list.append(proxies_items)
proxies_items = {'HTTP': 'HTTP://59.55.164.25:3256'}
proxies_list.append(proxies_items)
check_ip(proxies_list)
#### 测试网页使用代理IP
# t_url = 'https://wallhaven.cc/hot?page=5' ### 这个网站无法使用正常方式去获取正确编码的网页
# t_headers = {
# 'authority': 'wallhaven.cc',
# 'method': 'GET',
# 'path': '/hot?page=6',
# 'scheme': 'https',
# 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',
# 'accept-encoding': 'gzip, deflate, br',
# 'accept-language': 'zh-CN,zh;q=0.9',
# 'cache-control': 'max-age=0',
# 'cookie': '_pk_id.1.01b8=abe1922f5b6b4dbe.1627432653.; _pk_ses.1.01b8=1; XSRF-TOKEN=eyJpdiI6IjhWYndWZWxXZmkwTTh5RHVZWG4rakE9PSIsInZhbHVlIjoiXC9GZWZBU0cyd3FEd1dKSFZUdHA4bUF1WCtSRkVUcmM0VzJHcWM1QXRaNk11V0pDcFFOUGlXamJlXC9ubXlQODVLIiwibWFjIjoiNDgzNjUwMDlhYjFmN2M3MDQxOTdkYzAzZWUzZDA0NjQzYmUxYzE1NTczOTBhMWQ4MjRmNmQ4NzhjMmIxNzNiOCJ9; wallhaven_session=eyJpdiI6IjM1TnZXQ2ZPV3p5UkNHdUlcL1VQNWlnPT0iLCJ2YWx1ZSI6Ik9UUEk0XC8zcDdhOGNkcWtmOTFBMWtjZWhvN0FxNkVzWjN6TG9MeVV4SzBidE1yb3prVSt4ZytPWjNmZzdRSlJjIiwibWFjIjoiOGI1YWZmZGI3YTdlZjIxYTIyMTFlMzQxNGJjZjRiZGIxZTljYTJlYTcxNzE0MDEwZDg1NDA3OWQ5ZTEwZjk4ZCJ9',
# 'dnt': '1',
# 'upgrade-insecure-requests': '1',
# 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3870.400 QQBrowser/10.8.4405.400',
# }
# t_params = {
# "page": "6"
# }
# check_ip(proxies_list,False,t_url,t_headers,t_params)
先登录,后获取数据的原则。
# ## 登录headers
headers = {
'Accept': 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Content-Length': '1343',
'Content-Type': 'application/json;charset=UTF-8',
# 'Cookie': 'lianjia_uuid=1c467c64-7f14-4cc3-8bb6-7fbfeb0d8e9e; _smt_uid=62ca2925.4765cab8; sajssdk_2015_cross_new_user=1; _ga=GA1.2.1277253011.1657415976; _gid=GA1.2.572250099.1657415976; crosSdkDT2019DeviceId=-51d8ff--5mdcvr-fvmfmboapp9hu55-36vejykpe; lianjia_ssid=b7ade908-94e7-4cd6-933b-a4827c25ed16; select_city=310000; Hm_lvt_9152f8221cb6243a53c83b956842be8a=1657416994; sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22181e5b0bcb3351-050ae16361d442-26021a51-1327104-181e5b0bcb421d%22%2C%22%24device_id%22%3A%22181e5b0bcb3351-050ae16361d442-26021a51-1327104-181e5b0bcb421d%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_referrer%22%3A%22%22%2C%22%24latest_referrer_host%22%3A%22%22%2C%22%24latest_search_keyword%22%3A%22%E6%9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%7D%7D; Hm_lpvt_9152f8221cb6243a53c83b956842be8a=1657420005; JSESSIONID=81497D8D13D7CF413369F68F49CD7EE7',
'Host': 'clogin.lianjia.com',
'Origin': 'https://sh.lianjia.com',
'Pragma': 'no-cache',
'Referer': 'https://sh.lianjia.com/',
'sec-ch-ua': '".Not/A)Brand";v="99", "Google Chrome";v="103", "Chromium";v="103"',
'sec-ch-ua-mobile': '?0',
'sec-ch-ua-platform': '"Windows"',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-site',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
}
#
## 登录data
data = {
'accountSystem': 'customer',
'context': {
'clickPosX': '736',
'clickPosY': '237',
'clientSource': 'pc',
'os': 'Windows',
'osVersion': '10',
'registerPosLx': '609.6000366210938',
'registerPosLy': '223.6999969482422',
'registerPosRx': '909.6000366210938',
'registerPosRy': '606.4999847412109',
'screen': '1519_322',
'ua': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.0.0 Safari/537.36',
},
'credential':
{
'encodeVersion': '1',
'password': 'PkZWkCivOK2jIJZFw6BAFrFiaPq292iOxAhgQKHTYDulICbqytiEqSPScQf37NNTh/IfENOWHcGKL1YVVmW9iWvBnKLVpJCetRKldZUxSMQ9p0rquJGupY4Wz2ER0rt6S0cJtE96/caIVXeRMtIzyI/K4oCRCZ4t61lyBWldke8=',
'username': '13228827053',
},
'loginTicketId': 'VOldD3P9UMAOnMbZhgNP7Z1skv3BRe5T',
'mainAuthMethodName': 'username-password',
'service': 'https://ajax.api.lianjia.com/login/login/getuserinfo',
'srcId': 'eyJ0Ijoie1wiZGF0YVwiOlwiZGZhOTk2Y2VjOTEyNjI0ZDcyY2ZlZDI4NTBlMDU5ZmYxMTZiY2ExNDJiN2FlYjY5MTIxMWQyZTg0YjNjMmEyMDJiNTIwMDI3Njc3MWU5OGFhMzMyMjg1ZDg0NWZmMWUzNDBhNDIwNmE2NzdjYmMzYmI1YmQ2YjRiMDVlYTYwOWExMjQ1NDE2ZjhjN2ZiZDQ0YjVmZmMxNzMyOWUxOGZmYzk3YjdjOGM4MTRhMDU1YzlkOTdkYzQ5OWE0YjUwZDhjN2I2ODQyZjA4MTlmODI5ZDc0OWI3ZmY0MWVmZGVhOWNjZTM0MjRiNGY4MjUxM2YxYTViNzc1ODc0MTcwZTk3ZVwiLFwia2V5X2lkXCI6XCIxXCIsXCJzaWduXCI6XCIzNTc1OWQwNVwifSIsInIiOiJodHRwczovL3NoLmxpYW5qaWEuY29tLyIsIm9zIjoid2ViIiwidiI6IjAuMSJ9',
'ticketMaxAge': '604800',
'version': '2.0',
}
#
# ## 登录帐号
# username='13228827053'
# password='xxxxx'
#
# 提交登录,并保存登录的状态
session_requests = requests.session()
login_url = 'https://clogin.lianjia.com/authentication/authenticate'
# 提交登录表单
result = session_requests.post( url=login_url, data =data, headers = headers1 )
print("已经提交登录信息",result)
1.open方法
f = open('c:/Users/Icy-yun/Desktop/www2.txt', 'a+')
get_info(url)
f.write('\n\n----------第%d章已完结---------\n\n' %n)
f.close()
2.with方法
photo_data = requests.get(url = photo_url,headers=headers).content
with open(path + photo_name + '('+ str(n+i+1) + ')' + '.jpg',mode='wb') as f:
f.write(photo_data)
print(f'第{n+i+1}张图片已经下载完毕!') # {i+n}无法使用
f.close()
3.urllib方法
from urllib import request
图片不是.jpg或者.png的链接无法保存,获取的photo_url没有cookie的数据也无法在其它浏览器打开
request.urlretrieve(photo_url,path + photo_name + '('+ str(i+n) + ')'+'.jpg')
4.获取当前路径
path = os.getcwd() + '/音乐' # 当前路径下创建文件夹
os.makedirs(path, exist_ok=True) # 保证在当前路径下建立文件夹
path = f'{name}\\' # 当前路径下创建文件夹
if not os.path.exists(path): # 同os.makedirs(path,exist_ok=True)
os.makedirs(path)
"&".join("{0}={1}".format(k, v) for k, v in unsigned_items) # join 连接列表数据
pre_data = pre_data if pre_data else '' # 三目运算符数据
string = string.strip(xxxx)
if(string), and , is not, in, None
for i,item in enumerate(xxx) 枚举遍历
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oO6UjJVr-1661622494545)(C:\Users\Icy-yun\AppData\Roaming\Typora\typora-user-images\image-20220528125954218.png)]
1.open方法
if os.path.exists(dir):
f =open(dir,"r")
data = f.read ()
print(data)
f.close ()
2.with 方法
(1.with + for..in 直接读取(速度快)
with open('filepath','r') as f:
for line in f:
print(line)
print('一行数据')
(2.with + read 全部读取(占用内存)
with open('filepath','r') as f:
ff=f.read()
(3.with + readlines 按行读取
with open('filepath','r') as f:
lines =f.readline()
for line in lines:
print(line)
(1.csv 模块读写
import urllib,os,csv
csv文件操作
def openCSV(filename):
if not os.path.exists('./position'):
os.mkdir('position')
fp = open (f'./position/{filename}.csv', 'a+', newline='', encoding='utf-8-sig')
writer = csv.writer (fp)
writer.writerow (('经度','纬度','地铁站_500m','地铁站_1000m','地铁站_1500m','学校_500m','学校_1000m','学校_1500m','医院_500m','医院_1000m','医院_1500m','购物中心_500m','购物中心_1000m','购物中心_1500m'
))
return fp,writer
def writeCSV(writer,*data):
writer.writerow (tuple(data))
def closeCSV(fp):
fp.close()
读取csv文件
def readCSV(dir):
f = open(dir,encoding='utf8' )
reader = csv.reader(f)
for row in reader:
print(row)
originCSVDir = './123.csv'
readCSV(originCSVDir)
(2.实战事例
例11:爬取豆瓣音乐的音乐排行榜 --“本周音乐人最热单曲榜”的页面信息(CSV库保存)
import requests
from lxml import etree
import re
import csv
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 '
'(KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36'
}
print("正在加载网页数据。。。\n")
url = 'https://music.douban.com/chart'
res = requests.get(url,headers=headers)
selector = etree.HTML(res.text)
songs1 = selector.xpath('//*[@id="content"]/div/div[1]/div/ul/li/div/h3/a/text()')
songs2 = selector.xpath('//*[@id="content"]/div/div[1]/div/ul/li/div/p/a/text()')
singers1 = selector.xpath('//*[@id="content"]/div/div[1]/div/ul/li/div/p/text()')
singers2 = selector.xpath('//*[@id="content"]/div/div[1]/div/ul/li/div/p/text()')
xpath初始就是大标签时,则不用更改
print("已加载完毕!\n")
print('正在保存数据。。。')
fp=open('c://Users/Icy-yun/Desktop/www.csv','wt',newline='',encoding='utf-8-sig')
writer = csv.writer(fp)
writer.writerow(('歌名','歌手','播放量'))
n=0
for song,singer in zip(songs1,singers1):
singer_1=singer.split('/')[0]
singer_2=singer.split('/')[1]
print(song,' ',singer_1,' ',singer_2)
writer.writerow((song,singer_1,singer_2))
n+=1
for song in songs2:
n2=0
for singer2 in singers2:
if n2<=n: n2+="1" continue result="re.search" (' ', singer2) # 如果这条信息不是需要爬取的信息,则根据search查找':'是否存在 if none: 因为re.search返回的是一个对象,根据是否为none来控制是否退出循环 n+="1" singer2_1="re.sub('\n','',singer2,5)" singer2_2="re.sub('" ','',singer2_1,20) singer_1="singer2_2.split('/')[0]" singer_2="singer2_2.split('/')[1]" print(song,' ',singer_1,' ',singer_2) writer.writerow((song,singer_1,singer_2)) break fp.close() print("已保存数据!") 把得到的csv文件先用记事本打开,然后另存为带有bom的utf-8类型的xxx1.csv文件。可以打开 虽然无法在csv文件里面编辑,但可以复制到excel文件里面,进行编辑,保存的操作 < code></=n:>
注意:数据库的字符编码为utf8
1.使用方法
(1)导包 import pymysql
(2)创建连接对象 pymysql.connect(参数列表)
conn = connect(host='localhost',port=3306,user='root'
,password='xxxx',database='jing_dong',charset='utf8')
(3)获取游标对象 cursor =conn.cursor()
(4)执行SQL语句 row_count = cursor.execute(sql)
(5)获取查询结果集(查询) result = cursor.fetchall()
result = cursor.fetchone()
(6)将修改操作提交到数据库(添加,修改,删除) conn.commit()
(7)回滚数据 conn.rollback()
(8)关闭游标 cursor.close()
(9)关闭连接 conn.close()
2.crud 增删改查
import pymysql
创建连接对象
conn = pymysql.connect(host='localhost', port=3306, user='root', password='xxxx',database='python', charset='utf8')
获取游标对象
cursor = conn.cursor()
try:
# 添加 SQL 语句
# sql = "insert into students(name) values('刘璐'), ('王美丽');"
# 删除 SQ L语句
# sql = "delete from students where id = 5;"
# 修改 SQL 语句
sql = "update students set name = '王铁蛋' where id = 6;"
# 执行 SQL 语句
row_count = cursor.execute(sql)
print("SQL 语句执行影响的行数%d" % row_count)
# 提交数据到数据库
conn.commit()
except Exception as e:
# 回滚数据, 即撤销刚刚的SQL语句操作
conn.rollback()
关闭游标
cursor.close()
关闭连接
conn.close()
3.防止SQL注入
什么是SQL注入?用户提交带有恶意的数据与SQL语句进行字符串方式的拼接,从而影响了SQL语句的语义,最终产生数据泄露的现象。
如何防止SQL注入?
1.SQL语句参数化
SQL语言中的参数使用%s来占位,此处不是python中的字符串格式化操作, 将SQL语句中%s占位所需要的参数存在一个列表中,把参数列表传递给execute方法中第二个参数
防止SQL注入的示例代码(说明:execute方法中的 %s 占位不需要带引号):
from pymysql import connect
def main():
find_name = input("请输入物品名称:")
# 创建Connection连接
conn = connect(host='localhost',port=3306,user='root',password='xxxx',database='jing_dong',charset='utf8')
# 获得Cursor对象
cs1 = conn.cursor()
# 非安全的方式
# 输入 ' or 1 = 1 or ' (单引号也要输入)
# sql = "select * from goods where name='%s'" % find_name
# print("""sql===>%s<====""" % sql) # 执行select语句,并返回受影响的行数:查询所有数据 count="cs1.execute(sql)" 安全的方式 构造参数列表 params="[find_name]" * from goods where name="%s"," params) 注意: 如果要是有多个参数,需要进行参数化 那么params="[数值1," 数值2....],此时sql语句中有多个%s即可 %s 不需要带引号 打印受影响的行数 print(count) 获取查询的结果 result="cs1.fetchone()" 打印查询的结果 print(result) 关闭cursor对象 cs1.close() 关闭connection对象 conn.close() if __name__="=" '__main__': main() < code></====""">
例7:对MySQL数据库爬取的数据进行词频统计 -- (sql语句+jieba库)
import pymysql
import jieba.analyse
def get_sql(sql):
# 1.连接数据库
conn = pymysql.connect(host="127.0.0.1", user="root", passwd="xxxx", db="dangdang", charset="utf8",port=3306)
# 2.获取游标对象
cursor = conn.cursor()
# 3.执行SQL语句 (返回值是在执行中影响的行数)
rew_count = cursor.execute(sql)
# 4.取出结果集中的所有数据
print("SQL语句执行影响的行数" + str(rew_count))
content = ''
for line in cursor.fetchall():
content = content + line[0]
print(line[0], ' ', line[1])
jieba.analyse.set_stop_words('../otherFile/中文停用词表.txt') # ..表示当前路径下的上一级目录
tags = jieba.analyse.extract_tags(content, topK=100, withWeight=True)
for j,item in enumerate(tags):
print("第" + str(j + 1) + "名:" + item[0] + " 次数:" + str(int(item[1] * 1000)))
# 5.关闭游标,关闭连接
cursor.close()
conn.close()
if __name__=='__main__':
words = "'%Java%'"
sql = "select * from books where title like " + words
get_sql(sql)
1.res.encoding响应解码
unicode解码
res = requests.get(url,headers)
res.encoding = 'unicode_escape'
2.encode字符串解码
response.text.encode('unicode_escape')
1.引入上级
import sys
sys.path.append("..")
### 如果是当前页面使用,则需要添加到系统路径中
from ..config.request import getResponse
from config.request import getResponse
2.引入同级
引入所有模块
from .models import *
引入部分模块
from .models import Student
注意:如果需要封装在一个文件夹下,需要在新文件夹下添加_ init _.py文件
如果还要整体文件夹当作一个模块,文件夹下的文件作为子模块,,则需要在_ init _.py文件下添加以下内容
__all__ = [
'IndexViews',
'UsersViews',
]
Original: https://blog.csdn.net/qq_50792097/article/details/126564984
Author: 起航吧!少年
Title: python学习(二):python的数据挖掘技术,网络爬虫
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/639707/
转载文章受原作者版权保护。转载请注明原作者出处!